8

Starting with watchOS 2, we have an ExtensionDelegate object, which is analogous to UIApplicationDelegate (reacts to app lifecycle events).

I want to get a reference to the first Interface Controller object, which will be displayed upon launch, to set a property on it (e.g. pass in a data store object).

According to the docs, the rootInterfaceController property on WKExtension hands back the initial controller:

The root interface controller is located in the app’s main storyboard and has the Main Entry Point object associated with it. WatchKit displays the root interface controller at launch time, although the app can present a different interface controller before the launch sequence finishes.

So I try the following in ExtensionDelegate:

func applicationDidFinishLaunching() {
    guard let initialController = WKExtension.sharedExtension().rootInterfaceController else {
        return
    }

    initialController.dataStore = DataStore()
}

Even though the correct Interface Controller is displayed, rootInterfaceController is nil at this point. Interestingly if I query the same property in the willActivate() of my Interface Controller, the property is set correctly.

In an iOS app, you can already get the root view controller in applicationDidFinishLaunching(), and I thought it should work the same for watchOS.

Is there a way to set properties on my Interface Controller before it's displayed (from the outside)? Is this a bug?

Many thanks for the answer!

Lorenzo
  • 3,293
  • 4
  • 29
  • 56
József Vesza
  • 4,775
  • 3
  • 27
  • 42
  • Did you ever find the cause of this? @józsef-vesza – Wilmar Dec 01 '15 at 06:10
  • @Wilmar unfortunately no. It seems that `rootInterfaceController` is nil at this stage, so I ended up instantiating my properties in my interface controller subclasses. Not great, but that's the best I've got so far. :/ – József Vesza Dec 01 '15 at 08:41
  • Mm I see. I added a `dispatch_after` in my code, set it to 1 second, and then the `rootInterfaceController` property had the expected value. Quite frustrating. @józsef-vesza – Wilmar Dec 01 '15 at 08:58
  • Hm. Interesting. I didn't want to add any more delays (launch times are quite long already), but that's an interesting info, thanks! Yes, it's frustrating, I expected extension delegate to behave like app delegate in iOS. – József Vesza Dec 01 '15 at 09:00
  • Agreed about load times. I only added it to see if the value gets set eventually. Also had to re-architect my delegate logic to not depend on the callbacks. @józsef-vesza – Wilmar Dec 01 '15 at 09:32
  • I just bumped into this two. Sometimes I'm seeing `applicationDidFinishLaunching` fire twice, and in the second call `rootInterfaceController` is no longer nil. Very strange. Have you filed a radar? I'd be happy to dupe it. – Jeff V Jan 09 '16 at 23:38

2 Answers2

0

You might move your code to applicationDidBecomeActive.

This page describes the states of watch apps. When applicationDidFinishLaunching is invoked, the app is in an inactive state.

https://developer.apple.com/library/watchos/documentation/WatchKit/Reference/WKExtensionDelegate_protocol/index.html

Drewf
  • 414
  • 2
  • 7
0

If you are calling this from within another interface controller, try move the WKExtension.sharedExtension().rootInterfaceController to the willActivate() function. It seems like if it is in the awake() function it sometimes works but is unreliable.