22
UISplitViewController

The iPhone and iPod touch have a limited amount of screen real estate. Given their small screen size, when presenting a drill-down interface, a UINavigationController is used to swap between a list of items and a detailed view for an item.

The iPad, on the other hand, has plenty of screen space to present both views using a built-in class called UISplitViewController. UISplitViewController is an iPad-only class that presents two view controllers in a master-detail relationship. The master view controller occupies a small strip on the lefthand side of the screen, and the detail view controller occupies the rest of the screen.

In this chapter, you will have Nerdfeed present its view controllers in a split view controller when running on an iPad (Figure 22.1). You will also make Nerdfeed a universal application and have it continue to use a UINavigationController when run on the iPhone.

Figure 22.1  Nerdfeed with UISplitViewController

Nerdfeed with UISplitViewController

Splitting Up Nerdfeed

Creating a UISplitViewController is simple since you have already learned about navigation controllers and tab bar controllers. When you initialize a split view controller, you pass it an array of view controllers just like with a tab bar controller. However, a split view controller’s array is limited to two view controllers: a master view controller and a detail view controller. The order of the view controllers in the array determines their roles in the split view; the first entry is the master view controller, and the second is the detail view controller.

Open Nerdfeed.xcodeproj in Xcode. Then, open BNRAppDelegate.m.

In application:didFinishLaunchingWithOptions:, check whether the device is an iPad before instantiating a UISplitViewController. The UISplitViewController class does not exist on the iPhone, and trying to create an instance of UISplitViewController will cause an exception to be thrown.

-​ ​(​B​O​O​L​)​a​p​p​l​i​c​a​t​i​o​n​:​(​U​I​A​p​p​l​i​c​a​t​i​o​n​ ​*​)​a​p​p​l​i​c​a​t​i​o​n​
 ​ ​ ​ ​d​i​d​F​i​n​i​s​h​L​a​u​n​c​h​i​n​g​W​i​t​h​O​p​t​i​o​n​s​:​(​N​S​D​i​c​t​i​o​n​a​r​y​ ​*​)​l​a​u​n​c​h​O​p​t​i​o​n​s​
{​
 ​ ​ ​ ​s​e​l​f​.​w​i​n​d​o​w​ ​=​ ​[​[​U​I​W​i​n​d​o​w​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​F​r​a​m​e​:​[​[​U​I​S​c​r​e​e​n​ ​m​a​i​n​S​c​r​e​e​n​]​ ​b​o​u​n​d​s​]​]​;​

 ​ ​ ​ ​B​N​R​C​o​u​r​s​e​s​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​*​l​v​c​ ​=​
 ​ ​ ​ ​ ​ ​ ​ ​[​[​B​N​R​C​o​u​r​s​e​s​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​S​t​y​l​e​:​U​I​T​a​b​l​e​V​i​e​w​S​t​y​l​e​P​l​a​i​n​]​;​

 ​ ​ ​ ​U​I​N​a​v​i​g​a​t​i​o​n​C​o​n​t​r​o​l​l​e​r​ ​*​m​a​s​t​e​r​N​a​v​ ​=​
 ​ ​ ​ ​ ​ ​ ​ ​[​[​U​I​N​a​v​i​g​a​t​i​o​n​C​o​n​t​r​o​l​l​e​r​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​R​o​o​t​V​i​e​w​C​o​n​t​r​o​l​l​e​r​:​l​v​c​]​;​

 ​ ​ ​ ​B​N​R​W​e​b​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​*​w​v​c​ ​=​ ​[​[​B​N​R​W​e​b​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​
 ​ ​ ​ ​l​v​c​.​w​e​b​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​=​ ​w​v​c​;​

 ​ ​ ​ ​s​e​l​f​.​w​i​n​d​o​w​.​r​o​o​t​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​=​ ​m​a​s​t​e​r​N​a​v​;​
 ​ ​ ​ ​
 ​ ​ ​ ​/​/​ ​C​h​e​c​k​ ​t​o​ ​m​a​k​e​ ​s​u​r​e​ ​w​e​ ​a​r​e​ ​r​u​n​n​i​n​g​ ​o​n​ ​t​h​e​ ​i​P​a​d​
 ​ ​ ​ ​i​f​ ​(​[​U​I​D​e​v​i​c​e​ ​c​u​r​r​e​n​t​D​e​v​i​c​e​]​.​u​s​e​r​I​n​t​e​r​f​a​c​e​I​d​i​o​m​ ​=​=​ ​U​I​U​s​e​r​I​n​t​e​r​f​a​c​e​I​d​i​o​m​P​a​d​)​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​w​e​b​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​m​u​s​t​ ​b​e​ ​i​n​ ​n​a​v​i​g​a​t​i​o​n​ ​c​o​n​t​r​o​l​l​e​r​;​ ​y​o​u​ ​w​i​l​l​ ​s​e​e​ ​w​h​y​ ​l​a​t​e​r​
 ​ ​ ​ ​ ​ ​ ​ ​U​I​N​a​v​i​g​a​t​i​o​n​C​o​n​t​r​o​l​l​e​r​ ​*​d​e​t​a​i​l​N​a​v​ ​=​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​[​U​I​N​a​v​i​g​a​t​i​o​n​C​o​n​t​r​o​l​l​e​r​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​R​o​o​t​V​i​e​w​C​o​n​t​r​o​l​l​e​r​:​w​v​c​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​U​I​S​p​l​i​t​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​*​s​v​c​ ​=​ ​[​[​U​I​S​p​l​i​t​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​S​e​t​ ​t​h​e​ ​d​e​l​e​g​a​t​e​ ​o​f​ ​t​h​e​ ​s​p​l​i​t​ ​v​i​e​w​ ​c​o​n​t​r​o​l​l​e​r​ ​t​o​ ​t​h​e​ ​d​e​t​a​i​l​ ​V​C​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​Y​o​u​ ​w​i​l​l​ ​n​e​e​d​ ​t​h​i​s​ ​l​a​t​e​r​ ​-​ ​i​g​n​o​r​e​ ​t​h​e​ ​w​a​r​n​i​n​g​ ​f​o​r​ ​n​o​w​
 ​ ​ ​ ​ ​ ​ ​ ​s​v​c​.​d​e​l​e​g​a​t​e​ ​=​ ​w​v​c​;​

 ​ ​ ​ ​ ​ ​ ​ ​s​v​c​.​v​i​e​w​C​o​n​t​r​o​l​l​e​r​s​ ​=​ ​@​[​m​a​s​t​e​r​N​a​v​,​ ​d​e​t​a​i​l​N​a​v​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​S​e​t​ ​t​h​e​ ​r​o​o​t​ ​v​i​e​w​ ​c​o​n​t​r​o​l​l​e​r​ ​o​f​ ​t​h​e​ ​w​i​n​d​o​w​ ​t​o​ ​t​h​e​ ​s​p​l​i​t​ ​v​i​e​w​ ​c​o​n​t​r​o​l​l​e​r​
 ​ ​ ​ ​ ​ ​ ​ ​s​e​l​f​.​w​i​n​d​o​w​.​r​o​o​t​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​=​ ​s​v​c​;​
 ​ ​ ​ ​}​ ​e​l​s​e​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​O​n​ ​n​o​n​-​i​P​a​d​ ​d​e​v​i​c​e​s​,​ ​j​u​s​t​ ​u​s​e​ ​t​h​e​ ​n​a​v​i​g​a​t​i​o​n​ ​c​o​n​t​r​o​l​l​e​r​
 ​ ​ ​ ​ ​ ​ ​ ​s​e​l​f​.​w​i​n​d​o​w​.​r​o​o​t​V​i​e​w​C​o​n​t​r​o​l​l​e​r​ ​=​ ​m​a​s​t​e​r​N​a​v​;​
 ​ ​ ​ ​}​

 ​ ​ ​ ​s​e​l​f​.​w​i​n​d​o​w​.​b​a​c​k​g​r​o​u​n​d​C​o​l​o​r​ ​=​ ​[​U​I​C​o​l​o​r​ ​w​h​i​t​e​C​o​l​o​r​]​;​
 ​ ​ ​ ​[​s​e​l​f​.​w​i​n​d​o​w​ ​m​a​k​e​K​e​y​A​n​d​V​i​s​i​b​l​e​]​;​
 ​ ​ ​ ​r​e​t​u​r​n​ ​Y​E​S​;​
}​

By placing the UISplitViewController code within an if statement in this method, you are laying the groundwork for making Nerdfeed a universal application. Also, now you can see why you created the instance of BNRWebViewController here instead of following the typical pattern of creating the detail view controller inside the implementation for the root view controller. A split view controller must have both the master and the detail view controller when it is created. The diagram for Nerdfeed’s split view controller is shown in Figure 22.2.

Figure 22.2  Split view controller diagram

Split view controller diagram

Build and run the application. You may not see anything yet if you are in portrait mode; however, if you rotate the device to landscape you will see both view controllers on the screen. This is how a UISplitViewController works: in landscape mode, there master view controller is shown in a small strip on the left hand side of the screen and the detail view controller takes over the rest of the screen.

But you are not done yet. If you tap a row in the list view controller, the web view controller will not appear in the detail panel like you want. Instead, it is pushed onto the master panel and replaces the list view controller. To address this problem, when a row is tapped, you need to check whether the BNRCoursesViewController is a member of a split view controller and, if it is, take a different action.

You can send the message splitViewController to any UIViewController, and if that view controller is part of a split view controller it will return a pointer to the split view controller (Figure 22.3). Otherwise, it returns nil. View controllers are smart: a view controller will return this pointer if it is a member of the split view controller’s array or if it belongs to another controller that is a member of a split view controller’s array (as is the case with both BNRCoursesViewController and BNRWebViewController).

Figure 22.3  UIViewController’s splitViewController property

UIViewController’s splitViewController property

In BNRCoursesViewController.m, locate the method tableView:didSelectRowAtIndexPath:. At the top of this method, check for a split view controller before pushing the BNRWebViewController onto the navigation stack.

-​ ​(​v​o​i​d​)​t​a​b​l​e​V​i​e​w​:​(​U​I​T​a​b​l​e​V​i​e​w​ ​*​)​t​a​b​l​e​V​i​e​w​
 ​ ​ ​ ​d​i​d​S​e​l​e​c​t​R​o​w​A​t​I​n​d​e​x​P​a​t​h​:​(​N​S​I​n​d​e​x​P​a​t​h​ ​*​)​i​n​d​e​x​P​a​t​h​
{​
 ​ ​ ​ ​N​S​D​i​c​t​i​o​n​a​r​y​ ​*​c​o​u​r​s​e​ ​=​ ​s​e​l​f​.​c​o​u​r​s​e​s​[​i​n​d​e​x​P​a​t​h​.​r​o​w​]​;​
 ​ ​ ​ ​N​S​U​R​L​ ​*​U​R​L​ ​=​ ​[​N​S​U​R​L​ ​U​R​L​W​i​t​h​S​t​r​i​n​g​:​c​o​u​r​s​e​[​@​"​u​r​l​"​]​]​;​

 ​ ​ ​ ​s​e​l​f​.​w​e​b​V​i​e​w​C​o​n​t​r​o​l​l​e​r​.​t​i​t​l​e​ ​=​ ​c​o​u​r​s​e​[​@​"​t​i​t​l​e​"​]​;​
 ​ ​ ​ ​s​e​l​f​.​w​e​b​V​i​e​w​C​o​n​t​r​o​l​l​e​r​.​U​R​L​ ​=​ ​U​R​L​;​
 ​ ​ ​ ​[​s​e​l​f​.​n​a​v​i​g​a​t​i​o​n​C​o​n​t​r​o​l​l​e​r​ ​p​u​s​h​V​i​e​w​C​o​n​t​r​o​l​l​e​r​:​s​e​l​f​.​w​e​b​V​i​e​w​C​o​n​t​r​o​l​l​e​r​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​a​n​i​m​a​t​e​d​:​Y​E​S​]​;​
 ​ ​ ​ ​
 ​ ​ ​ ​ ​i​f​ ​(​!​s​e​l​f​.​s​p​l​i​t​V​i​e​w​C​o​n​t​r​o​l​l​e​r​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​ ​[​s​e​l​f​.​n​a​v​i​g​a​t​i​o​n​C​o​n​t​r​o​l​l​e​r​ ​p​u​s​h​V​i​e​w​C​o​n​t​r​o​l​l​e​r​:​s​e​l​f​.​w​e​b​V​i​e​w​C​o​n​t​r​o​l​l​e​r​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​a​n​i​m​a​t​e​d​:​Y​E​S​]​;​
 ​ ​ ​ ​ ​}​
 ​ ​ ​ ​
}​

Now, if the BNRCoursesViewController is not in a split view controller, you assume the device is not an iPad and BNRCoursesViewController pushes the BNRWebViewController onto the navigation controller’s stack. If BNRCoursesViewController is in a split view controller, then it is left to the UISplitViewController to place the BNRWebViewController on the screen.

Build and run the application again. Rotate to landscape and tap one of the rows. The class web page will now load in the detail panel.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset