Page Based "Reloadrootcontrollerswithnames:" on Launch Loop

Page Based reloadRootControllersWithNames: on launch loop?

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.

WatchKit reloadRootControllersWithNames causing error, with pageController or after push/pop

I was able to solve my instance of this problem by not using popController on a pushed view controller. Instead I use a reloadRootControllersWithNames in place of the popController.

How this allows both push and paging, via an example:

  1. Push a view controller
  2. reloadRootControllersWithNames to return to the original controller. (The transition is not quite as animated, but is sufficient)
  3. Create page based view controller.
  4. reloadRootControllersWithNames to return to the original controller
  5. Repeat 1 or 3 as needed.

This eliminates the error at the cost of non-animated popControllers, and allows partial pushing and paging. It would not allow more complex push navigation though.

There may be a better method of navigating to a sub interface controller without a push call, but I'm not aware of it on the watch yet.

Page based interface use multiple of the same viewcontrollers

Assuming that you have associated the same InterfaceController for each of your page, to pass different data to each of the page follow undermentioned steps:

  1. Create a initial view controller, which will act like a splash
    screen for your app.
  2. In "willActivate" of initial view controller, create an array of
    pages and an array of contexts with the data that you need to pass
    to each of these pages(interfaceViewControllers).
  3. Call WKInterfaceController.reloadRootControllersWithNames(pages,
    contexts: pageContexts).
  4. In "awakeWithContext" of your common InterfaceController for each of
    the pages, read the context and initialise properties/data.

Point no. 3 basically ensures that your pages are displayed as if directly launched. Other option you've is to use self.presentControllerWithNames, but that will show a "Cancel" button on top left.

Example Code:
In SplashScreen Interface Controller

override func willActivate() {
super.willActivate()
let pages = ["page1","page2","page3","page4"]
let pageContexts = [["data1":0,"data2":0],["data1":38,"data2":1],["data1":49,"data2":1],["data1":74,"data2":2]]
WKInterfaceController.reloadRootControllersWithNames(pages, contexts: pageContexts)
}

In Page Interface Controller

override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)

if let contextDict:Dictionary = context as Dictionary<String,AnyObject>!
{
data1 = contextDict["data1"] as Int
data2 = contextDict["data2"] as NSTimeInterval
}
}

How to reuse WKInterfaceTable in WatchKit

You should create a single interface controller with the table and various row types. Then you want to create an architecture very similar to my answer here. You'll only have a single PageOneInterfaceController which should be named TableInterfaceController in this example with TableInterfaceIdentifier as the identifier. Then you would do the following:

MainInterfaceController.swift

func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)

let context1 = "context 1 - for you to fill out"
let context2 = "context 2 - for you to fill out"
let context3 = "context 3 - for you to fill out"

WKInterfaceController.reloadRootControllersWithNames(
["TableInterfaceIdentifier", "TableInterfaceIdentifier", "TableInterfaceIdentifier"],
contexts: [context1, context2, context3]
)
}

This will reload the page set using the same interface controller that displays all the data in the respective context.



Related Topics



Leave a reply



Submit