- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
[WKInterfaceController reloadRootControllersWithNames:@[@"pageOne", @"pageTwo"] contexts:nil];
}
Following Apple's guidelines
Call this method to reload the pages in your app’s page-based interface. At launch time, you use this method to customize the set of pages you want displayed.
at launch time, only results in a loop. With each reload calling awakeWithContext or will Activate or init again and again.
Is there a better way to go about reloading the Page-Based app on launch with a loop occurring?
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
}
}