Last active
May 21, 2024 18:21
-
-
Save NatashaTheRobot/6bcbe79afd7e9572edf6 to your computer and use it in GitHub Desktop.
WatchConnectivity Singleton Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// WatchSessionManager.swift | |
// WatchConnectivityDemo | |
// | |
// Created by Natasha Murashev on 9/3/15. | |
// Copyright © 2015 NatashaTheRobot. All rights reserved. | |
// | |
import WatchConnectivity | |
class WatchSessionManager: NSObject, WCSessionDelegate { | |
static let sharedManager = WatchSessionManager() | |
private override init() { | |
super.init() | |
} | |
private let session: WCSession? = WCSession.isSupported() ? WCSession.defaultSession() : nil | |
private 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 let session = session where session.paired && session.watchAppInstalled { | |
return session | |
} | |
return nil | |
} | |
func startSession() { | |
session?.delegate = self | |
session?.activateSession() | |
} | |
} | |
// 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 { | |
try session.updateApplicationContext(applicationContext) | |
} catch let error { | |
throw error | |
} | |
} | |
} | |
// Receiver | |
func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) { | |
// handle receiving application context | |
dispatch_async(dispatch_get_main_queue()) { | |
// 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, didFinishUserInfoTransfer userInfoTransfer: WCSessionUserInfoTransfer, error: NSError?) { | |
// 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 : AnyObject]) { | |
// handle receiving user info | |
dispatch_async(dispatch_get_main_queue()) { | |
// 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, metadata: metadata) | |
} | |
func session(session: WCSession, didFinishFileTransfer fileTransfer: WCSessionFileTransfer, error: NSError?) { | |
// handle filed transfer completion | |
} | |
// Receiver | |
func session(session: WCSession, didReceiveFile file: WCSessionFile) { | |
// handle receiving file | |
dispatch_async(dispatch_get_main_queue()) { | |
// 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 where session.reachable { | |
return session | |
} | |
return nil | |
} | |
// Sender | |
func sendMessage(message: [String : AnyObject], | |
replyHandler: (([String : AnyObject]) -> Void)? = nil, | |
errorHandler: ((NSError) -> Void)? = nil) | |
{ | |
validReachableSession?.sendMessage(message, replyHandler: replyHandler, errorHandler: errorHandler) | |
} | |
func sendMessageData(data: NSData, | |
replyHandler: ((NSData) -> Void)? = nil, | |
errorHandler: ((NSError) -> Void)? = nil) | |
{ | |
validReachableSession?.sendMessageData(data, replyHandler: replyHandler, errorHandler: errorHandler) | |
} | |
// Receiver | |
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { | |
// handle receiving message | |
dispatch_async(dispatch_get_main_queue()) { | |
// make sure to put on the main queue to update UI! | |
} | |
} | |
func session(session: WCSession, didReceiveMessageData messageData: NSData, replyHandler: (NSData) -> Void) { | |
// handle receiving message data | |
dispatch_async(dispatch_get_main_queue()) { | |
// make sure to put on the main queue to update UI! | |
} | |
} | |
} |
// handle receiving message data
DispatchQueue.main.async() {
// make sure to put on the main queue to update UI!
}
if this is on the watch side, how to access UI elements from here? Thanks!
Swift 5.0+ Version:
Both for iOS and WatchOS targets
import WatchConnectivity
class WatchSessionManager: NSObject, WCSessionDelegate {
static let sharedManager = WatchSessionManager()
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)
func sessionDidBecomeInactive(_ session: WCSession) {
}
func sessionDidDeactivate(_ session: WCSession) {
}
#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 {
return session
}
#elseif os(watchOS)
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 {
try session.updateApplicationContext(applicationContext)
} catch let error {
throw error
}
}
}
// Receiver
func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
// handle receiving application context
DispatchQueue.main.async {
// 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!
}
}
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!
}
}
}
also can be found in the gist
didReceiveApplicationContext not called
i have used startSession() in appdelegate
after i sent params on updateApplicationContext
and am not getting called didReceiveApplicationContext func
@Manikarthi-vaiha in the past didReceiveApplicationContext
did not work properly on simulator (If your problem occured on simulator), please see the documentation for details.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you are using @kayoslab version it has some wrong method names e.g.
func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject])
should be
func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:])
for exampleThe easiest way to find such problems is to make Watch app call these and then run iOS App in debug. WCSession on phone often prints in console if there is something wrong. You can clearly see if you miss a delegate method. WCSession on watch app does not do it.