- Developing with Navigation Controllers and Split Views
- Recipe: Building a Simple Two-Item Menu
- Recipe: Adding a Segmented Control
- Recipe: Navigating Between View Controllers
- Recipe: Presenting a Custom Modal Information View
- Recipe: Page View Controllers
- Recipe: Scrubbing Pages in a Page View Controller
- Recipe: Tab Bars
- Recipe: Remembering Tab State
- Recipe: Building Split View Controllers
- Recipe: Creating Universal Split View/Navigation Apps
- Recipe: Custom Containers and Segues
- One More Thing: Interface Builder and Tab Bar Controllers
- Summary
Recipe: Creating Universal Split View/Navigation Apps
Recipe 5-10 modifies Recipe 5-9's split view controller to provide a functionally equivalent application that runs properly on both iPhone and iPad platforms. Accomplishing this takes several steps that add to Recipe 5-9's code base. You do not have to remove functionality from the split view controller approach but you must provide alternatives in several places.
Recipe 5-10 depends on a macro that is used throughout which determines whether the code is being run on an iPad- or iPhone-style device:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
This macro returns YES when the device characteristics are iPad-like, rather than being iPhone-like (such as on the iPhone or iPod touch.) First introduced in iOS 3.2, idioms allow you to perform runtime checks in your code to provide interface choices that match the deployed platform.
In an iPhone deployment, the detail view controller remains code identical to Recipe 5-9, but to be displayed it must be pushed onto the navigation stack rather than shown side-by-side in a split view. The navigation controller is set up as the primary view for the application window rather than the split view. A simple check at application launch lets your code choose which approach to use:
- (UINavigationController *) navWithColorViewController { ColorViewController *colorViewController = [ColorViewController controller]; UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:colorViewController]; return nav; } - (void)applicationDidFinishLaunching:(UIApplication *)application { window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; if (IS_IPAD) window.rootViewController = [self splitviewController]; else window.rootViewController = [self navWithColorViewController]; [window addSubview:mainController.view]; [window makeKeyAndVisible]; }
The rest of the story lies in the two methods of Recipe 5-10, within the color-picking table view controller. Two key checks decide whether to show disclosure accessories and how to respond to table taps:
- On the iPad, disclosure indicators should never be used at the last level of detail presentation. On the iPhone, they indicate that a new view will be pushed on selection. Checking for deployment platform lets your code choose whether or not to include these accessories in cells.
- When you're working with the iPhone, there's no option for using split views, so your code must push a new detail view onto the navigation controller stack. Compare this to the iPad code, which only needs to reach out to an existing detail view and update its background color.
In real-world deployment, these two checks would likely expand in complexity beyond the details shown in this simple recipe. You'd want to add a check to your model to determine if you are, indeed, at the lowest level of the tree hierarchy before suppressing disclosure accessories. Similarly, you may need to update or replace presentations in your detail view controller.
Recipe 5-10. Adding Universal Support for Split View Alternatives
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"generic"]; if (!cell) cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:@"generic"]; cell.textLabel.text = @"Brightness"; cell.textLabel.textColor = [UIColor colorWithWhite:(indexPath.row / 10.0f) alpha:1.0f]; cell.accessoryType = IS_IPAD ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; if (IS_IPAD) { UIViewController *controller = (UIViewController *)self.splitViewController.delegate; controller.view.backgroundColor = cell.textLabel.textColor; } else { DetailViewController *controller = [ DetailViewController controller]; controller.view.backgroundColor = cell.textLabel.textColor; [self.navigationController pushViewController:controller animated:YES]; } }