Read iOS Programming: The Big Nerd Ranch Guide, 3/e (Big Nerd Ranch Guides) Online
Authors: Aaron Hillegass,Joe Conway
Tags: #COM051370, #Big Nerd Ranch Guides, #iPhone / iPad Programming
Notice that here again you have left a non-split view controller, non-iPad option in an
else
clause that pushes the
ChannelViewController
onto the navigation controller’s stack.
Build and run the application. After the RSS feed loads, tap the
Info
button. The detail view controller will display the metadata for the channel. However, if you tap on a post after you’ve loaded the metadata, nothing will happen – you can’t get back to a web view.
This is because the navigation controller that held the web view controller was only owned by the split view controller. So when we replaced it with a navigation controller holding the channel view controller in
showInfo:
, the first navigation controller was destroyed. We have to create another navigation controller that holds the web view controller and give it to the split view controller.
In
ListViewController.m
, modify the
tableView:didSelectRowAtIndexPath:
to place a navigation controller with the
WebViewController
in the split view controller.
Build and run the application. You should be able to move back and forth between the two detail view controllers.
The
ListViewController
doesn’t know how to show a post in a web view or show the info for the
RSSChannel
. So it
delegates
those behaviors to other objects.
ListViewController
does know about the
ListViewControllerDelegate
protocol, and it sends that protocol’s message to a conforming detailed view controller to handle things it can’t.
Even though the
ListViewController
never sets either of the detail view controllers as its
delegate
, this is still delegation. Delegation is a design pattern, not a naming convention. For another example, the table view-data source relationship is delegation, even though the variable the table view sends messages to is called
dataSource
.
While in portrait mode, the master view controller is missing in action. It would be nice if you could see the master view controller to select a new post from the list without having to rotate the device.
UISplitViewController
lets you do just that by supplying its delegate with a
UIBarButtonItem
. Tapping this button shows the master view controller in a
UIPopoverController
(
Figure 26.5
).
Figure 26.5 Master view controller in UIPopoverController
In your code, whenever a detail view controller was given to the split view controller, that detail view controller was set as the split view controller’s delegate. As the delegate, the detail view controller will get a pointer to the
UIBarButtonItem
when rotating to portrait mode.
Since both
WebViewController
and
ChannelViewController
can be the delegate for a
UISplitViewController
, it’s best to declare that they conform to the
UISplitViewControllerDelegate
protocol.
In
WebViewController.h
, add this declaration:
And do the same in
ChannelViewController.h
.
Build and run the application. The behavior will be the same, but there won’t be any warnings.
In
WebViewController.m
, implement the following delegate method to place the bar button item in the
WebViewController
’s navigation item.
Notice that we explicitly set the title of the button. If the button doesn’t have a title, it won’t appear at all. (If the master view controller’s
navigationItem
has a title, then the button will be automatically set to that title. )
Build and run the application. Rotate to portrait mode, and you will see the bar button item appear on the left of the navigation bar. Tap that button, and the master view controller’s view will appear in a
UIPopoverController
.
This bar button item is why we always had you put the detail view controller inside a navigation controller. You don’t have to use a navigation controller to put a view controller in a split view controller, but it makes using the bar button item much easier. (If you don’t use a navigation controller, you can instantiate your own
UINavigationBar
or
UIToolbar
to hold the bar button item and add it as a subview of the
WebViewController
’s view.)
There are two small issues left to address with your
List
button. First, when the device is rotated back to landscape mode, the button is still there. To remove it, the delegate needs to respond to another message from the
UISplitViewController
. Implement this delegate method in
WebViewController.m
.
Build and run the application. The
List
button will now appear and disappear as you rotate between portrait and landscape modes.
The second issue is that the
ChannelViewController
also needs to show the
List
button. In
ChannelViewController.m
, implement the two
UISplitViewControllerDelegate
methods.
Build and run the application. Now the
List
button will also appear on the navigation bar when the
ChannelViewController
is on the screen.
(There is a third issue: while in portrait mode, if you switch between the
ChannelViewController
and the
WebViewController
, you lose the bar button item. Fixing this problem is one of the challenges at the end of this chapter.)
When first creating
Nerdfeed
, we chose to go with an iPad-only application. Now let’s turn it into a universal application. Select the
Nerdfeed
project from the project navigator. In the editor area, choose the
Nerdfeed
target and then the
Summary
tab.
Figure 26.6 Universalizing Nerdfeed
From the
Devices
pop-up menu, choose
Universal
.
Figure 26.7 Changing simulators
That’s all there is to it – the application is now universal. You can test it by building and running again on one simulator and then the other.
There are two reasons the universalization process was so easy for
Nerdfeed
. Remembering these reasons will help you when you’re writing your own applications.