import WatchConnectivity class WatchSessionManager: NSObject, WCSessionDelegate { static let sharedManager = WatchSessionManager() public var watchDelegate: WatchSessionDelegate? private override init() { super.init() } private let session: WCSession? = WCSession.isSupported() ? WCSession.default : nil @available(iOS 9.3, *) func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { #if os(iOS) print("******** Session Activated ******") print("Watch is paired \(session.isPaired)") print("Watch is reachable \(session.isReachable)") print("Watch app installed \(session.isWatchAppInstalled)") #endif //print("Watch is reachable \(session.isReachable)") } #if os(iOS) func sessionDidBecomeInactive(_ session: WCSession) { print("Session Inactive") } func sessionDidDeactivate(_ session: WCSession) { print("Session deactivated") } #endif var validSession: WCSession? { // paired - the user has to have their device paired to the watch // watchAppInstalled - the user must have your watch app installed // Note: if the device is paired, but your watch app is not installed // consider prompting the user to install it for a better experience #if os(iOS) if let session = session, session.isPaired && session.isWatchAppInstalled { print("Watch is paired \(session.isPaired)") print("Watch app installed \(session.isWatchAppInstalled)") return session } #elseif os(watchOS) print("Watch is reachable \(session!.isReachable)") return session #endif return nil } func startSession() { session?.delegate = self session?.activate() } } // MARK: Application Context // use when your app needs only the latest information // if the data was not sent, it will be replaced extension WatchSessionManager { // Sender func updateApplicationContext(applicationContext: [String : AnyObject]) throws { if let session = validSession { do { print("WCSession contect sent \(applicationContext)") try session.updateApplicationContext(applicationContext) print("WCSession contect sent \(applicationContext)") } catch let error { throw error } }else{ print("Error sending context") } } // Receiver func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) { // handle receiving application context let isEnabledStatus = applicationContext["isEnabled"] as? Bool // DispatchQueue.main.async { print("Received application context \(applicationContext) 1") #if os(watchOS) if watchDelegate != nil{ print("Received application context \(applicationContext) 2") watchDelegate?.updateConectionStatus(isEnabled: isEnabledStatus ?? false) } #endif // make sure to put on the main queue to update UI! // } } } // MARK: User Info // use when your app needs all the data // FIFO queue extension WatchSessionManager { // Sender func transferUserInfo(userInfo: [String : AnyObject]) -> WCSessionUserInfoTransfer? { return validSession?.transferUserInfo(userInfo) } func session(_ session: WCSession, didFinish userInfoTransfer: WCSessionUserInfoTransfer, error: Error?) { // implement this on the sender if you need to confirm that // the user info did in fact transfer } // Receiver func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) { // handle receiving user info DispatchQueue.main.async { // make sure to put on the main queue to update UI! } } } // MARK: Transfer File extension WatchSessionManager { // Sender func transferFile(file: NSURL, metadata: [String : AnyObject]) -> WCSessionFileTransfer? { return validSession?.transferFile(file as URL, metadata: metadata) } func session(_ session: WCSession, didFinish fileTransfer: WCSessionFileTransfer, error: Error?) { // handle filed transfer completion } // Receiver func session(_ session: WCSession, didReceive file: WCSessionFile) { // handle receiving file DispatchQueue.main.async { // make sure to put on the main queue to update UI! } } } // MARK: Interactive Messaging extension WatchSessionManager { // Live messaging! App has to be reachable private var validReachableSession: WCSession? { if let session = validSession , session.isReachable { return session } return nil } // Sender func sendMessage(message: [String : AnyObject], replyHandler: (([String : Any]) -> Void)? = nil, errorHandler: ((Error) -> Void)? = nil) { validReachableSession?.sendMessage(message, replyHandler: replyHandler, errorHandler: errorHandler) } func sendMessageData(data: Data, replyHandler: ((Data) -> Void)? = nil, errorHandler: ((Error) -> Void)? = nil) { validReachableSession?.sendMessageData(data, replyHandler: replyHandler, errorHandler: errorHandler) } // Receiver func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) { // handle receiving message DispatchQueue.main.async { // make sure to put on the main queue to update UI! print("Message Received\(message)") } } func session(_ session: WCSession, didReceiveMessageData messageData: Data) { // handle receiving message data DispatchQueue.main.async { // make sure to put on the main queue to update UI! } } }