Page Based “reloadRootControllersWithNames:” on launch loop?

北慕城南 提交于 2019-11-28 10:06:09

This is a common problem with WatchKit apps since we no longer have a UIApplicationDelegate to handle such set up. A good approach would be to structure your code as follows:

  • MainInterfaceController (the main link in storyboard points here)
  • PageOneInterfaceController - your first interface to display in the page set
  • PageTwoInterfaceController - your second interface in the page set

The MainInterfaceController will never actually get displayed. You will always launch into a different set of interface controllers depending on the cached state of the companion iOS App in MainInterfaceController.awakeWithContent(). This way, you use the MainInterfaceController in a similar manner that we use the UIApplicationDelegate in iOS to set up the window and root view controller.

I have used this approach in an app that had many different page sets to choose from and it worked very well.

That is why awakeWithContext: exists. The first time your app is launched, the initial controller is passed nil as context. But if you reloadRootControllersWithNames:contexts:, you have an opportunity to pass a custom context instance and thus distinguish the launch mode.

calling WKInterfaceController.reloadRootControllers causes the awake function to be called a second time. This is the solution I use - it is straight forward, compact, and eliminates the recursive loop. This example has two page based views called mainControls and nowPlaying that are configured with contexts. Note the key thing here is to configure the mainControls view controller with an empty string context then that context is checked and returns if it is being called again due to the WKInterfaceController.reloadRootControllers statement that configured the context to "". Note the first time awake runs the context for the main view controller will be nil. Also note the second context is an implementation detail specific to my implementation - this could be any object that you want to pass to the second view controller.

override func awake(withContext context: Any?) {
    super.awake(withContext: context)
    if let _ = context as? String {
        print("already configured!")
        return
    }
    print("configuring...")
    WKInterfaceController.reloadRootControllers(withNames: ["mainControls", "nowPlaying"], contexts: ["", interaction])
}

Really easy to solve, and does not require Multiple Page Controllers -- Just use once

Create a class variable (not an instance variable) and use that as your flag to ensure that your call to reloadRootControllers is only ever called once.

static NSString* hasLaunchedIfNotNullString = NULL;

- (void)awakeWithContext:(id)context
{
    if(hasLaunchedIfNotNullString == NULL)
    {
        //START Code which gets executed once
        hasLaunchedIfNotNullString = @"";

        ...
        [WKInterfaceController reloadRootControllersWithNames:YOUR_ARRAY contexts:CONTEXTS];
        // END code which gets executed once
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!