-
You should not send or receive custom class objects from one target(iOS) to second target(watchOS) instead you should send/receive data in dictionary format such as [String: Any] and this dictionary should contain array of your custom objects required properties in key value pair in simple dictionary. This could easily be decodable at watch side.
-
You should make a decoupled class extending WCSessionDelegate such as below so that this class could be used not only in ExtensionDelegate but also in any WKInterfaceController.
class WatchSessionManager: NSObject, WCSessionDelegate { static let sharedManager = WatchSessionManager() private override init() { super.init() self.startSession() } private let session: WCSession = WCSession.default func startSession() { session.delegate = self session.activate() } func tryWatchSendMessage(message: [String: Any], completion: (([String: Any]) -> Void)? = nil) { print("tryWatch \(message)") weak var weakSelf = self if #available(iOS 9.3, *) { if weakSelf?.session.activationState == .activated { if weakSelf?.session.isReachable == true { weakSelf?.session.sendMessage(message, replyHandler: { [weak self] ( response ) in guard let slf = self else {return} //Get the objects from response dictionary completion?(response) }, errorHandler: { [weak self] ( error ) in guard let slf = self else {return} print ( "Error sending message: % @ " , error ) // If the message failed to send, queue it up for future transfer slf.session.transferUserInfo(message) }) } else { self.session.transferUserInfo(message) } }else{ self.session.activate() self.session.transferUserInfo(message) } } else { // Fallback on earlier versions if self.session.activationState == .activated { if self.session.isReachable == true { self.session.sendMessage(message, replyHandler: { ( response ) in //Get the objects from response dictionary completion?(response) }, errorHandler: { ( error ) in print ( "Error sending message: % @ " , error ) // If the message failed to send, queue it up for future transfer self.session.transferUserInfo(message) }) } else { self.session.transferUserInfo(message) } }else{ self.session.activate() self.session.transferUserInfo(message) } } } }
Now you could easily send a message to your iOS app to wake up and get data from there (e.g from CoreData) using the above function in any WKInterfaceController and the completion block will have your required data such as
let dict: [String: Any] = ["request": "FirstLoad"]
WatchSessionManager.sharedManager.tryWatchSendMessage(message: dict,completion:{ (data) in print(data)})
Same way you should use this WatchSessionManager on iOS side and receive the request and as per the requested key you should take data from core storage/db and send list of custom objects in simple key-value Dictionary pattern within replyHandler of didreceiveMessage function such as below.
func session(_ session: WCSession, didReceiveMessage message: [String: Any], replyHandler: @escaping ([String: Any]) -> Void) {
var dict: [String: Any] = [String: Any]()
replyHandler(dict) //This dict will contain your resultant array to be sent to watchApp.
}
Some time iOS App(Killed state) is not reachable to WatchApp, for solving that problem you should call “tryWatchSendMessage” within Timer of around 3 sec interval. And when you get connection from watchApp then you should invalidate the timer.
The sendMessage functionality of WatchConnectivity is so powerful to wake your app up. You should use it in optimized manner.