Watch OS 1.0.1 Controller Life Cycle Changes

Today, Apple released OS 1.0.1 for Apple Watch. Among a list of other updates, the release notes mention performance improvements for third-party apps. I was curious to see if this OS update fixed the disappearing status bar bug, and indeed, it did. Thank you, Apple!

I also noticed that the WatchKit Controller Life Cycle that I detailed in my prior post has changed slightly in OS 1.0.1. Unfortunately, these changes affect the heuristics I was using to work around the status bar bug, and because the fix is associated with an OS version (and not an iOS version), I am left with no method to determine when to apply the workaround. This is due to the fact that there seems to be no way to programmatically determine the Watch OS version. But enough about my troubles.

From what I’ve gathered so far, it looks like there are two changes to the general WKInterfaceController life cycle:

  • When a page-based set of interface controllers are loaded, the prior OS 1.0.0 initialization sequence occurs first, followed by two new calls to willActivate and didDeactivate on the next controller (in this case, Page 2). Presumably, Apple added these calls so that the next controller is primed and ready to go by the time the user moves it into view.
  • When an app is moved back into the foreground (for example, after being suspended), willActivate is called before the two NSExtensionContext notifications. In OS 1.0.0, willActivate is called after those notifications.

I’ve added a third page to the diagram to illustrate the fact that not all controllers receive the new willActivate and didDeactivate calls when they’re loaded; they’re only sent to the next controller in the sequence. Changes are highlighted in yellow.

The documentation for willActivate states that it is:

Called to let you know that the interface controller’s contents are onscreen.

Clearly, in the new speculative willActivate/didDeactivate sequence, the contents are not onscreen. But, the documentation goes on to say:

Activation can happen at any time, including while the user’s iPhone is locked.

Okay…so willActivate can be called at any time. But then, the documentation for didDeactivate states:

Called to let you know that the interface controller’s contents are now offscreen.

It’s difficult to imagine content going offscreen if it’s never been onscreen in the first place. It seems to me that the meaning of these two events has changed in OS 1.0.1.

You might ask: so what? Well, for straightforward WatchKit apps, the addition of these two speculative willActivate/didDeactivate calls are like a free perceptual performance boost. Your “next page” now has a chance to configure itself with fresh data before the page is truly displayed onscreen. If this is your scenario, you’re in great shape.

However, If—like me—you use these methods to determine which interface controller a user is currently viewing, these events have now lost a key component of their meaning. In my app, I use this information to intelligently pre-cache assets on a background thread just before they’re needed. I will have to reconsider how to accomplish the same goal in OS 1.0.1. And because I can’t detect the Watch OS version, I have no way to modify the behavior for users who are still running 1.0.0.

As always, happy coding!

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *