What is the recommended way to read UserDefaults from iPhone in WatchOS2

I need to get a number from

userDefaults
from the iPhone to use in an Apple Watch app to make some calculations. I heard that you can no longer use Share App Groups in WatchOS2 and that we should use the WatchConnectivity framework instead. I also heard that you could send the UserDefaults from iPhone as read-only to the Watch but I cannot find any information on this.


In the following code I'm using the WatchConnectivity framework to get a double from userDefaults but what I don't like about the way I have it right now is that the Phone only sends the data to the Watch when the iPhone app is loaded (viewDidLoad), in other words if I launch the Watch app I need to open the iPhone app in order to get the data to the Apple Watch.


What is the recomended way to share iPhone UserDefaults with the Watch in WatchOS2?


Here is what I have which as I described above needs manual interction on the Phone to be able to send the information.


iOS View Controller


class ViewController: UIViewController, WCSessionDelegate {
    var session: WCSession!

    override func viewDidLoad() {
        super.viewDidLoad()
     
        if WCSession.isSupported() {
            session = WCSession.default()
            session.delegate = self
            session.activate()
        }
    }

    func session(_ session: WCSession, activationDidCompleteWith activationState:WCSessionActivationState, error: Error?) {}
    func sessionDidDeactivate(_ session: WCSession) { }
    func sessionDidBecomeInactive(_ session: WCSession) { }

    func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
        // Reply to watch with data from user defaults
        replyHandler(["dataFromiPhone": readDoubleFromUserDefaults()])
    }
}


WatchOS InterfaceController


class InterfaceController: WKInterfaceController, WCSessionDelegate{

    var session: WCSession!

    var myNumber:Double = 0
   
    override func willActivate() {
        super.willActivate()
       
        if (WCSession.isSupported()) {
            session = WCSession.default()
            session.delegate = self
            session.activate()
        }
        getDataFromiPhone()
    }
   
    override func didDeactivate() {
        super.didDeactivate()
    }
    /// Delegate required method
    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {}

    func getDataFromiPhone(){
        //Send Message to phone - I'm not sure if I need this message
        let messageToSend = ["askiPhone":"Hi Phone, send me data from userDefaults."]
        session.sendMessage(messageToSend, replyHandler: { replyMessage in
            /// handle the reply
            let dataFromPhone = replyMessage["dataFromiPhone"] as? String
            DispatchQueue.main.async {
                self.myNumber = Double(dataFromPhone!)!
            }
        }, errorHandler: {error in
            /// catch any errors here
            print("ERROR: \(error)")
        })
    }
}

Replies

Hey guys, any recommendations on this?

The above code does not have the above problem because:


https://developer.apple.com/documentation/watchconnectivity/wcsession/1615687-sendmessage?language=objc

"Calling this method from your WatchKit extension while it is active and running wakes up the corresponding iOS app in the background and makes it reachable."


Alternatively, you could use this whenever the iOS app updates its value:

https://developer.apple.com/documentation/watchconnectivity/wcsession/1615621-updateapplicationcontext?language=objc

"Use this method to transfer a dictionary of data items to the counterpart app. The system sends context data when the opportunity arises, with the goal of having the data ready to use by the time the counterpart wakes up."