Reputation: 31283
I have a SplitViewController
with a UITableViewController
as the masterViewController and a UIViewController
as the detailViewController.
When the user taps a cell, I need to push to a new UITableViewController
. So I added a segue from the cell to a UITableViewController
. But what happens is the UITableViewController
gets added to the masterViewController's stack.
How can I push to a whole new UITableViewController
from the masterViewController?
Upvotes: 3
Views: 2599
Reputation: 31283
I got it! First I should mention Michal's answer helped me to get an idea and point me in the right direction so thanks to him.
What I did was simple actually. Before I had a View Controller with a container view embedding the split view controller. I simply went ahead and embedded that view controller in a navigation controller.
Then I added the view controller I want to segue to in the storyboard but no segue attached to it. I'm doing it programatically in the masterViewController's didSelectRowAtIndexPath method.
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
if let rootVC = appDelegate.window?.rootViewController {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let mapVC = storyboard.instantiateViewControllerWithIdentifier("MapVC") as! UIViewController
rootVC.showViewController(mapVC, sender: nil)
}
I get a reference to the rootViewController which is a navigation controller through the AppDelegate and I push the new view controller I want to it's stack.
That's it! Here's a demo project in case anyone's interested.
Upvotes: 3
Reputation: 15669
Here is a simple example how I approach such functionality (I created a new Master-Detail Application):
Storyboard:
Notice that the root VC is now a UINavigationController
. Therefore AppDelegate
must be changed accordingly:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let navCtr = self.window!.rootViewController as UINavigationController
let splitViewController = navCtr.visibleViewController as UISplitViewController
let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as UINavigationController
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
splitViewController.delegate = self
return true
}
And then finally in MasterViewController
add this:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if indexPath.row % 2 == 0 {
self.performSegueWithIdentifier("showDetail", sender: nil)
} else {
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
if let let rootCtr = appDelegate.window?.rootViewController {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let newSplit = storyboard.instantiateViewControllerWithIdentifier("SplitVC") as UISplitViewController
/// Because of Apple's "Split View Controllers cannot be pushed to a Navigation Controller"
let yetAnotherNavCtr = UINavigationController(rootViewController: newSplit)
rootCtr.presentViewController(newSplit, animated: true, completion: nil)
}
}
}
Important notes:
If you create new MasterDetail Application from the template, you have to disconnect the showDetail
segue, because it is directly linked to the cell's selected
callback. If you want to preserve that functionality as well, simply connect it again not from the cell itself, but from the whole VC. To be able to use it as in my funky didSelect...
method that performs the showDetail
segue on even rows.
The Split View presentation will work only once - I haven't implemented the whole rootViewController replacement - the lldb will complain saying: Attempt to present UISplitViewController on UINavigationController whose view is not in the window hierarchy!
if you'll try to do it for the second time. But that's really up to your requirements for how you want the app to behave.
Name the SplitView Controller in Storyboard
"SplitVC" (Storyboard ID) if you want to present the Split View Controller like I am doing in my code.
Upvotes: 3