Rodrigo Lira Rodrigo Lira - 1 month ago 4
iOS Question

How do I perform a segue from a dynamic UITableView to a UINavigationController used as Detail Segue from a UISplitViewController?

I have a standard setup in place to use

UISplitViewController
. Here it is:

Initial setup for UISplitViewController

As per almost every guide I found for
UISplitViewController
, in order for everything to work properly, I need to create a segue from my
UITableViewController
(which is the Master and acts as a menu for the application) to the Detail
UINavigationController
.

Once I create this segue, selecting any of the (dynamically generated) cells of the
UITableView
will display the same Detail VC inside the Detail
UINavigationController
.

Now, what I really want is to add for every cell selected, one new
ViewController
is pushed into the navigation stack of the detail
UINavigationController
.

How do I do this? Should I keep the segue between the TableView and the Detail
UINavigationController
?

What I've tried so far:

1 - On the TableView's delegate, I've overwritten
didSelectRowAtIndexPath
and from there I called
UISplitViewController.showDetailViewController
.

But doing that "loses" the context of the NavigationController. The new controller seems to be pushed over the NavigationController. And because of that, I lose navigation bar and so on.

2 - I've overwritten
prepareForSegue
on
UITableViewController
and from there I detect that the destination is my Detail Navigation Controller. The only way I've found to try and push a VC into its navigation stack is the function
showViewController
but doing that inside
prepareForSegue
messes everything up (I start to get multiple views displayed at once).

So, in the context of a Master Detail project, how can I have the TableViewController act as a menu and perform a segue pushing the new VC into the detail navigation controller?

Answer

What you want seems to be what UISplitViewControllers are supposed to do, and when correctly configured, it is what they do do. To see this, make a new project in Xcode based on the Master Detail app template and run it. In the master view, make a few new table view cell entries with the Plus button. Now tap a cell. The detail view is replaced correctly with a view controller's view displaying that cell's value:

enter image description here

That is the standard behavior. So if that's what you want, just do what the template does, in the way that the template shows you how to do it.

EDIT Here's an example of doing the same thing in such a way that each table view cell shows something different:

enter image description here

EDIT 2 If you want to make things even more customizable, you should use code, not a storyboard segue. That in fact is what I usually do. I find it much cleaner to manage my split view controller in code, like this:

override func tableView(_ tableView: UITableView, 
    didSelectRowAt indexPath: IndexPath) {
        let detail = DetailViewController()
        detail.boy = model[indexPath.row]
        let b = self.splitViewController?.displayModeButtonItem
        detail.navigationItem.leftBarButtonItem = b // *
        detail.navigationItem.leftItemsSupplementBackButton = true
        let nav = UINavigationController(rootViewController: detail)
        self.showDetailViewController(nav, sender: self)
}

In that code, we are always making a DetailViewController in the first line, but this could be any view controller, and it could be a different view controller depending on what row was selected.

Comments