How to segue *without* storyboard between Master and Detail view?

2.1k views Asked by At

I've create a Master-Detail project completely programmatically, that is to say there is no storyboard whatsoever (I deleted the files).

What I cannot figure out is how to segue between the Master View (MV) and the Detail View (DV)

I've tried

self.showViewController(detailViewController, sender: self)

and

self.showDetailViewController(detailViewController, sender: self)

from the MV, but it doesn't really work.

My MV's table is filled with cells which, when pressed, should zoom to an annotation on the mapView in my DV.

For some reason, the map on the DV and the table in the MV do not refresh after they load the first time when the app opens.

I'm using a custom object to pass the data between the views

MV:

    detailViewController.setRequired(self.customObject)

    self.showDetailViewController(detailViewController, sender: self)

    self.tableView.reloadData()

Where "setRequired" is a function that sets the DV's class variables to the updated values from the MV (this part, at least, works)

DV:

super.viewDidLoad()

    mapView = MKMapView()
    mapView.mapType = .Standard
    mapView.frame = view.frame
    mapView.delegate = self
    view.addSubview(mapView)

    self.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
    self.navigationItem.leftItemsSupplementBackButton = true

    populateMap(extractedObject)

where "populateMap" is a function that takes the object (the values are correct, no worries) and is meant to populate the map with the new information.

As I said, the mapView doesn't update, and the table doesn't either.

Any ideas?

(reminder, there is no storyboard file, on purpose of course)

Thanks in advance!

Jona

EDIT

Following vacawama's answer:

Yes, my masterViewController is embedded in a UINavigationController. in viewDidLoad of the MVC I have

let controllers = self.splitViewController!.viewControllers
self.detailViewController =  controllers[controllers.count-1].topViewController as DetailViewController}, 

but when I try self.navigationController.pushView... suggested, I get the following error:

fatal error: unexpectedly found nil while unwrapping an Optional value

on the line let controllers = ...

EDIT to the Edit

Even after curing the found nil problem, the map and table just don't seem to upload. Any ideas?

1

There are 1 answers

1
vacawama On BEST ANSWER

Segues are a Storyboard creation. If you don't have a Storyboard, you can't segue. If your masterViewController is embedded in a UINavigationController, the programmatic way to move to the detailViewController is:

self.navigationController.pushViewController(detailViewController, animated: true)

If your masterViewController is not embedded in a UINavigationController, then you can present the detailViewController modally:

self.presentViewController(detailViewController, animated: true, completion: nil)

Update:

In your updated question, you mentioned SplitViewController. My initial answer gave you information for iPhone. For the SplitViewController, both the Master and Detail are onscreen at the same time so no loading of new ViewControllers is necessary (which is what a segue does). Just write the data you need to send to the detailViewController to a property or properties and then call a method to have the detailViewController to refresh it's view. You could even do that automatically using didSet on a property in the detailViewController.

Note, viewDidLoad will not run when you update the detailViewController. You need to extract the code which updates the UI of the detailViewController. Call it something like updateUI. Then call updateUI from both viewDidLoad and when your data gets updated. I suggest implementing didSet on your customData property and call updateUI from there.