ioswatchos-2watchconnectivitystate-restoration

Debugging and state restoration concerns of WatchOS WCSession sendMessage waking killed iPhone app


I'm trying to add simple WatchOS 2.0 functionality to my app to allow simple actions to be triggered on the watch and have an effect in my main app on the iPhone. All of this hinges by sending messages from the watch using WCSession's sendMessage method

[[WCSession defaultSession] sendMessage:applicationData
                         replyHandler:^(NSDictionary *reply) {
                           //handle reply from iPhone app here
                           DbgLog(@"reply received=%@", reply);
                         }
                         errorHandler:^(NSError *error) {
                           //catch any errors here
                           DbgLog(@"error received=%@", error);
                         }
 ];

Everything is working ok so far, the message is sent, the message is received, my app reacts correctly. I can even have my app backgrounded and everything seems to still work ok (I can see on the watch whether or not the iPhone has reacted to the messages as the iPhone will update the watch connectivity context which is then reflected back on the watch). I just want to start debugging the edge cases now.

My main two worries are...

How exactly can I debug the system waking up my app if it's been killed. I obviously can't spawn the process from Xcode, if i try to attach to the process it'll obviously be too late, ideally i'd like to be able to get break points set really early to see how things work. Worse case I can rely on lots of logs I guess and look at those. Just wondering if there's a good way of trying to debug this scenario?

Finally, what happens in this killed app being ran by the sendMessage being sent scenario with regards to state restoration. ie.

My problem is that the app still has its state encoding saved in state A when it was originally backgrounded.

Is there any way I can force a new state encode to occur whilst backgrounded after I've finished processing the watch connectivity sendMessage?

What happens when I next open my app properly, does state restoration occur which brings us back to state A when having processed the watch sendMessage it should be in state B. I'm guessing its still running in the background so whatever has occurred when the app spawned the app in the background should persist and no new state restoration should occur. However what if the system kills the app again whilst backgrounded in state B. Does it appreciate this scenario requires a new state encode to save the new state B or does it just kill the app and do nothing. If so then when we finally do freshly launch it then we may again be heading back to app state A rather than B.

As an aside, having just started to try and debug this sort of thing, though without the ability to seemingly connect my debugger for this system re-ran instance of my iPhone app. I've noticed that when I do the sendMessage that should wake up the killed iPhone app, the watch app does NOT update properly, ie. the phone app doesn't fully perform the action that has been requested. I'm currently blind at what things have taken place in this state, but wonder if perhaps state restoration could be getting in the way. Is the message received, waking the app, trying to act on data that doesn't exist as no state restoration has occurred yet, then state restoration occurs.. the 2nd time i send the message from the watch the app behaves correctly, so its as if the initial message wakes the app up but for some reason doesn't correctly process the message. Once woke up properly however the next sendMessage is handled as normal.

Sorry I find the documentation rather vague on what occurs when the iPhone app is background re-ran from a sendMessage call. Anyone got any ideas? Your time as always is really appreciated! Cheers!


Solution

  • Background and State Restoration:

    Your app which was launched in the background (then terminated) will never save state, because it never transitions from foreground to background (which is when state preservation happens).

    From Preserving and Restoring State:

    UIKit preserves your app’s state at appropriate times, such as when your app moves from the foreground to the background.

    The reason why it doesn't save state is because it is launched directly into the background.

    From The App Life Cycle:

    In addition, an app being launched directly into the background enters [the background state] instead of the inactive state.

    Debugging an app launched in the background:

    As for attaching to your app when it is launched in the background from a terminated state, there's a question which already provides the correct approach for this scenario.

    If you have specific questions about that, please leave a comment with the author of that answer.