Similar to Instagram and other popular apps, I'd like one of the buttons in my UITabBarController to present its view controller as a full-screen modal instead of a normal tab. I've used Storyboards to connect the UITabBarController to all of its child view controllers and I can't figure out how to present the one view controller as a modal. I found some other questions on here asking about the same thing but they seem to be assembling the tab bar manually instead of using segues like I did. Is this even possible the way I'm doing it?
2 Answers
tldr - Check out the code below.
I started with axxixc's approach but ran into some issues. I was attempting to show the view modally by implementing tabBarController:shouldSelectViewController:
of UITabBarControllerDelegate
. However, iOS was complaining about the view already being in the view hierarchy, which is obvious once you think about it because the whole point of using the UITabBarController in IB is so that iOS handles instantiating these views for us. So next I removed the view from it's parent and that stopped the errors but the approach still felt wrong and brittle. It also didn't give me any control over whether I wanted to re-instantiate the view each time the model popped up, which in my case I did.
So what I ended up doing is, in IB, connecting that specific tab to an empty view controller that would effectively act as a placeholder. I override the same tabBarController:shouldSelectViewController:
method and check for the title of the view controller. If it matches the dummy title that I set in IB, I stop the tab bar controller from showing the dummy controller by returning false
after showing my own view modally.
Here's the code:
func tabBarController(tabBarController: UITabBarController!, shouldSelectViewController viewController: UIViewController!) -> Bool {
if viewController.title? == DUMMY_POST_VIEW_CONTROLLER_TITLE {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let actualController = storyboard.instantiateViewControllerWithIdentifier("ActualViewController") as ActualViewController
presentViewController(actualController, animated: true, completion: nil)
return false
}
return true
}
I have a very strong suspicion that Instagram is using a totally custom tab bar, but if you wanted to do this using standard UIKit I'd say a good place to look would be subclassing UITabBarController
and overriding some of its UITabBarDelegate
methods, specifically -[UITabBarDelegate tabBar:didSelectItem:]
.