paulstringer / StoryboardsRevisited

Demo Code from Storyboards Revisited Talk, Swift Summit, San Francisco, 2016
73 stars 4 forks source link

Visiting UINavigationController/StoryboardNavigationController #2

Open rbsgn opened 8 years ago

rbsgn commented 8 years ago

Hi,

Thank you for sharing the idea of using visitors with storyboard segues! I've tried to incorporate your technique into Master-Detail Application template and found an issue which I don't know how to resolve elegantly with your technique.

Master-Detail Application template uses UISplitViewController where master view controller (basically a UITableViewController subclass) presents detail view controller which is wrapped into UINavigationController. This means that UINavigationController or (StoryboardNavigationController?) must conform to StoryboardVisitableScene and it must implement func accept(visitor: StoryboardController). How does accept should be implemented? Should I try to cast every possible root view controller of a navigation controller and call visit like that?

extension StoryboardNavigationController: StoryboardVisitableScene {
  func accept(visitor: StoryboardController) {
    if let masterViewController = topViewController as? MasterViewController {
      visitor.visit(masterViewController)
    }
    else if let detailViewController = topViewController as? DetailViewController {
      visitor.visit(detailViewController)
    }
  }
}

Ping me if you need a sample project.

rbsgn commented 8 years ago

What's interesting is that Show Detail segue gets called before tableView:didSelectRowAtIndexPath: and detail view controller ends up with no data from context supplied by master view controller.

rbsgn commented 8 years ago

I published my playground project at https://github.com/rbuussyghin/VisitedStoryboards for your convenience.

paulstringer commented 7 years ago

Thanks I'll take a look at the work you've done, interested to find the limitations which may well exist. In my example it was necessary for me to subclass and create Visitable versions of the standard UIKit ViewControllers and then change the Controller classes used in my storyboard. These are in the file "StoryboardViewController.swift" and I think it might only require that you take this and add one for UISplitViewController.

paulstringer commented 7 years ago

What's interesting is that Show Detail segue gets called before tableView:didSelectRowAtIndexPath: and detail view controller ends up with no data from context supplied by master view controller.

It's the case that when you have storyboard triggered segues from table view cells prepare(for ..) happens first and so typically you move the work from didSelect: to prepare(for ...) - in our case that means to the "StoryboardController" extension. DidSelect is almost redundant in this approach.

The trick is to get the data you want from the source during this processing. In my examples I've achieved this via a 'context' object which is the receiver of data from the different view controllers. So for instance you might in the TableViewController class override prepare(for ..) set the selected data for the next screen to the context based on tableView.indexPathOfSelectedCell and then call super prepare(for ...) where the destination can be configured using data captured to the context.