how to wake up iOS parent app with sendMessage fro

2019-05-18 14:37发布

I am trying to wake up the iOS parent app by sending a message from watchkit extension.

This though does only work when below sendMessage function is called from the watchApp / ViewController. When it is called from ComplicationController, the message is sent, but the iOS parent app does now wake up.

Any advice appreciated. (please any code reference in Swift)

Here the simplified code:

In AppDelegate and ExtensionDelegate:

override init() {
    super.init()
    setupWatchConnectivity()
}

private func setupWatchConnectivity() {
    if WCSession.isSupported() {
        let session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
}

In ExtensionDelegate: (no problem here, message is successfully sent)

func sendMessage(){
        let session = WCSession.defaultSession()
        let applicationData:[String:AnyObject] = ["text":"test", "badgeValue": 100 ]

        session.sendMessage(applicationData, replyHandler: {replyMessage in
            print("reply received from iphone")
            }, errorHandler: {(error ) -> Void in
                // catch any errors here
                print("no reply message from phone")
        })
    }
    print("watch sent message")

}

In AppDelegate: (not received when iOS app not running / not in foreground)

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    let text = message["text"] as! String
    let badgeValue = message["badgeValue"] as! Int

    dispatch_async(dispatch_get_main_queue()) { () -> Void in

        print("iphone received message from watch App")
        self.sendNotification(text, badgeValue: badgeValue)
        let applicationDict = ["wake": "nowAwake"]
        replyHandler(applicationDict as [String : String])

    }

}

this is how the function is called from Complication Controller (which does send the message but not awake the parent app):

  func requestedUpdateDidBegin(){

        dispatch_async(dispatch_get_main_queue()) { () -> Void in

            let extensionDelegate = ExtensionDelegate()
            extensionDelegate.loadData()

        }
    }

1条回答
Lonely孤独者°
2楼-- · 2019-05-18 14:46

The main problem is that you're trying to include (nested) asynchronous calls within your complication data source. However, your requested update will have reached the end of its method, and no timeline update will actually take place (since you didn't reload or extend the timeline, and even if you had, no new data would have been received in time for the current update).

Since no new data would be available for the scheduled update, you'd have to perform a second update to use the new data once it was received. Performing two back-to-back updates is not only unnecessary, it wastes more of your daily complication budget.

Apple recommends that you fetch and cache the data in advance of the update, so the complication data source can directly return the requested data to the complication server.

The job of your data source class is to provide ClockKit with any requested data as quickly as possible. The implementations of your data source methods should be minimal. Do not use your data source methods to fetch data from the network, compute values, or do anything that might delay the delivery of that data. If you need to fetch or compute the data for your complication, do it in your iOS app or in other parts of your WatchKit extension, and cache the data in a place where your complication data source can access it. The only thing your data source methods should do is take the cached data and put it into the format that ClockKit requires.

How can you update the complication?

Both of these approaches have the advantage of only needing one update to occur.

查看更多
登录 后发表回答