Welcome to Day 5 in the 31 Days of iOS. In yesterday’s article, we showed a few different ways to display a second view controller in our app. Specifically, we looked at pushing a view controller onto the view hierarchy of a Navigation Controller and how to present a view controller as a modal. Both of these techniques demonstrated ways to display view controllers via storyboards. Today we’re going to follow up by showing how to programmatically display view controllers. You can download the code we’re going to start with (from yesterday’s article) here. If you do so, you’ll need to remove the segues between the two view controllers. If you’d like to follow along with the completed code, you can access it here.
A UI Reminder
Just as a reminder, this is what our UI looks like right now in the storyboard (with no segues between the view controllers):
We’re going to make the navigation bar button (the one that says “item”) present the second view controller by pushing it onto the Navigation Controller. Then we’ll look at showing the second view controller as a modal when the user taps the Show New Video button.
Pushing a view
First while you’re in the storyboard, open the Assistant editor. We’re going to control + click and drag from the Item button to the .h file. You’re going to create a new Action named tappedNavButton:
There is one other thing we need to do in the storyboard before we can switch to the code. Select the view tied to SecondViewController and open the Identity Inspector in the Utilities view. Here we need to set the Storyboard ID:
After connecting that, switch over to your view controller’s .m file. Here, we’ll implement the tappedNavButton method:
If you’ve pushed a view controller before when Xcode used individual Xib (pronounced NIB) files for user interfaces, then this may look a little weird. Instead of just allocating a new instance of the SecondViewController and pushing that, you need to use the instance of the UIStoryboard that is tied to the view controller you’re in to instantiate the second one. We had to set an identifier in the storyboard so the storyboard would be able to recognize which one we wanted to instantiate. If you tried to just instantiate and push an instance of the SecondViewController, the application would run but the view would appear black. This is because it can still create an instance of the view controller but the code isn’t tied to any user interface. Now if you run your app and tap the bar button item it will push the second view correctly.
Showing a modal
Now we’ll show how to display a view controller in a modal. Open up the storyboard file and click + drag and drop the Show New View button to the .h file (using the Assistant Editor). Create a new action named tappedShowNewView:
Now let’s switch over to the .m file and see how we implement that method:
Again we’re instantiating the SecondViewController using the storyboard. Instead of pushing the view controller, we’re calling presentModalViewController. Now when you run the app and tap the Show New View button, you’ll see the second view controller as a modal.
UPDATE 1-7-2013: As Venkata has pointed out below, the presentModalViewController has been deprecated in iOS 6.0 (this article was written pre-release of 6.0). Going forward, you should be using [self presentViewController:secondViewController animated:YES completion:nil] in place of the deprecated method.
Conclusion
Today we saw how to display view controllers programmatically. Now you’re fully capable of displaying view controllers through the storyboard builder and in your code. Keep in mind that both of the code side techniques are only useful for displaying view controllers programmatically when their UIs are defined in storyboards. If you’re using Xibs, you can just alloc and init the view controller. You can download the final code from today here.
14 Comments
Venkata Koppaka
Worth noting presentModalViewController is deprecated as of iOS 6.0 suggested call is below
[self presentViewController:secondViewController animated:YES completion:Nil];
Chris
Thanks for pointing that out. I'd actually written this article before iOS 6 was fully available so I had missed that (I think you'll see in later articles I'm no longer using methods that are depreciated in 6.0). I'll note this above.
Venkata Koppaka
I was just wondering, are Segues considered bad for any purpose? while following along with your tutorial I found Segues more intuitive as opposed to programmatically invoking a view. Plus there is a visual element in the story board that the Segues added which showed the navigation clearly.(which I liked better than programmatically invoking a view)
Chris
In so far as I know, segues are not considered bad. Prior to using storyboards, developers had separate xib files for each View Controller and didn't have segues. While I think using storyboards (and segues) is the new "default" it's still possible to showing and hiding views programmatically. It's something that not everyone will do or need to do, but something that's worth covering for the cases where it's required (i.e. presenting a view that's part of a framework, etc)
Louis M Lozano
I liked it! Nice tutorial! It was easy and it worked! Thanks so much! http://www.frameforge3d.com/
bob woodley
We are supposed to manually add the import statement for SecondViewController.h then?
Chris
Yes, the import statement isn't mentioned but is something you'll need to do.
Jay Wong
Thank you Chris for the tutorial. I have tried to link page 1 to page 2, then from page 2 to page 3 by using storyboard id. It works fine between page 1 and page 2. However, I could not link page 2 to page 3. There is no error messages. Do we need to add any other code in order to link page 2 to page 3?
Jay Wong
Solved the problem. Typo mistake. I used presentedViewController instead of presentViewController. Thank again Chris, excellent tutorial.
Chris
Awesome to hear :)
Cameron Bourke
For some reason, when it performs the segue to the next view controller, it presents a blank white view controller instead of the controller I assigned it to?
Cameron Bourke
Update, I found the problem. I was assigning instigating it to one of my view controllers, instead of the root view controller. Thanks, it works great!
Chris
Awesome!
kiran kumar G
Thank you chris