- •Contents at a Glance
- •About the Authors
- •About the Technical Reviewer
- •Acknowledgments
- •Preface
- •What This Book Is
- •What You Need
- •Developer Options
- •What You Need to Know
- •What’s Different About Coding for iOS?
- •Only One Active Application
- •Only One Window
- •Limited Access
- •Limited Response Time
- •Limited Screen Size
- •Limited System Resources
- •No Garbage Collection, but…
- •Some New Stuff
- •A Different Approach
- •What’s in This Book
- •What’s New in This Update?
- •Are You Ready?
- •Setting Up Your Project in Xcode
- •The Xcode Workspace Window
- •The Toolbar
- •The Navigator View
- •The Jump Bar
- •The Utility Pane
- •Interface Builder
- •New Compiler and Debugger
- •A Closer Look at Our Project
- •Introducing Xcode’s Interface Builder
- •What’s in the Nib File?
- •The Library
- •Adding a Label to the View
- •Changing Attributes
- •Some iPhone Polish—Finishing Touches
- •Bring It on Home
- •The Model-View-Controller Paradigm
- •Creating Our Project
- •Looking at the View Controller
- •Understanding Outlets and Actions
- •Outlets
- •Actions
- •Cleaning Up the View Controller
- •Designing the User Interface
- •Adding the Buttons and Action Method
- •Adding the Label and Outlet
- •Writing the Action Method
- •Trying It Out
- •Looking at the Application Delegate
- •Bring It on Home
- •A Screen Full of Controls
- •Active, Static, and Passive Controls
- •Creating the Application
- •Implementing the Image View and Text Fields
- •Adding the Image View
- •Resizing the Image View
- •Setting View Attributes
- •The Mode Attribute
- •Interaction Checkboxes
- •The Alpha Value
- •Background
- •Drawing Checkboxes
- •Stretching
- •Adding the Text Fields
- •Text Field Inspector Settings
- •Setting the Attributes for the Second Text Field
- •Creating and Connecting Outlets
- •Closing the Keyboard
- •Closing the Keyboard When Done Is Tapped
- •Touching the Background to Close the Keyboard
- •Adding the Slider and Label
- •Creating and Connecting the Actions and Outlets
- •Implementing the Action Method
- •Adding Two Labeled Switches
- •Connecting and Creating Outlets and Actions
- •Implementing the Switch Actions
- •Adding the Button
- •Connecting and Creating the Button Outlets and Actions
- •Implementing the Segmented Control Action
- •Implementing the Action Sheet and Alert
- •Conforming to the Action Sheet Delegate Method
- •Showing the Action Sheet
- •Spiffing Up the Button
- •Using the viewDidLoad Method
- •Control States
- •Stretchable Images
- •Crossing the Finish Line
- •The Mechanics of Autorotation
- •Points, Pixels, and the Retina Display
- •Autorotation Approaches
- •Handling Rotation Using Autosize Attributes
- •Configuring Supported Orientations
- •Specifying Rotation Support
- •Designing an Interface with Autosize Attributes
- •Using the Size Inspector’s Autosize Attributes
- •Setting the Buttons’ Autosize Attributes
- •Restructuring a View When Rotated
- •Creating and Connecting Outlets
- •Moving the Buttons on Rotation
- •Swapping Views
- •Designing the Two Views
- •Implementing the Swap
- •Changing Outlet Collections
- •Rotating Out of Here
- •Common Types of Multiview Apps
- •The Architecture of a Multiview Application
- •The Root Controller
- •Anatomy of a Content View
- •Building View Switcher
- •Creating Our View Controller and Nib Files
- •Modifying the App Delegate
- •Modifying BIDSwitchViewController.h
- •Adding a View Controller
- •Building a View with a Toolbar
- •Writing the Root View Controller
- •Implementing the Content Views
- •Animating the Transition
- •Switching Off
- •The Pickers Application
- •Delegates and Data Sources
- •Setting Up the Tab Bar Framework
- •Creating the Files
- •Adding the Root View Controller
- •Creating TabBarController.xib
- •The Initial Test Run
- •Implementing the Date Picker
- •Implementing the Single-Component Picker
- •Declaring Outlets and Actions
- •Building the View
- •Implementing the Controller As a Data Source and Delegate
- •Implementing a Multicomponent Picker
- •Declaring Outlets and Actions
- •Building the View
- •Implementing the Controller
- •Implementing Dependent Components
- •Creating a Simple Game with a Custom Picker
- •Writing the Controller Header File
- •Building the View
- •Adding Image Resources
- •Implementing the Controller
- •The spin Method
- •The viewDidLoad Method
- •Final Details
- •Linking in the Audio Toolbox Framework
- •Final Spin
- •Table View Basics
- •Table Views and Table View Cells
- •Grouped and Plain Tables
- •Implementing a Simple Table
- •Designing the View
- •Writing the Controller
- •Adding an Image
- •Using Table View Cell Styles
- •Setting the Indent Level
- •Handling Row Selection
- •Changing the Font Size and Row Height
- •Customizing Table View Cells
- •Adding Subviews to the Table View Cell
- •Creating a UITableViewCell Subclass
- •Adding New Cells
- •Implementing the Controller’s Code
- •Loading a UITableViewCell from a Nib
- •Designing the Table View Cell in Interface Builder
- •Using the New Table View Cell
- •Grouped and Indexed Sections
- •Building the View
- •Importing the Data
- •Implementing the Controller
- •Adding an Index
- •Implementing a Search Bar
- •Rethinking the Design
- •A Deep Mutable Copy
- •Updating the Controller Header File
- •Modifying the View
- •Modifying the Controller Implementation
- •Copying Data from allNames
- •Implementing the Search
- •Changes to viewDidLoad
- •Changes to Data Source Methods
- •Adding a Table View Delegate Method
- •Adding Search Bar Delegate Methods
- •Adding a Magnifying Glass to the Index
- •Adding the Special Value to the Keys Array
- •Suppressing the Section Header
- •Telling the Table View What to Do
- •Putting It All on the Table
- •Navigation Controller Basics
- •Stacky Goodness
- •A Stack of Controllers
- •Nav, a Hierarchical Application in Six Parts
- •Meet the Subcontrollers
- •The Disclosure Button View
- •The Checklist View
- •The Rows Control View
- •The Movable Rows View
- •The Deletable Rows View
- •The Editable Detail View
- •The Nav Application’s Skeleton
- •Creating the Top-Level View Controller
- •Setting Up the Navigation Controller
- •Adding the Images to the Project
- •First Subcontroller: The Disclosure Button View
- •Creating the Detail View
- •Modifying the Disclosure Button Controller
- •Adding a Disclosure Button Controller Instance
- •Second Subcontroller: The Checklist
- •Creating the Checklist View
- •Adding a Checklist Controller Instance
- •Third Subcontroller: Controls on Table Rows
- •Creating the Row Controls View
- •Adding a Rows Control Controller Instance
- •Fourth Subcontroller: Movable Rows
- •Creating the Movable Row View
- •Adding a Move Me Controller Instance
- •Fifth Subcontroller: Deletable Rows
- •Creating the Deletable Rows View
- •Adding a Delete Me Controller Instance
- •Sixth Subcontroller: An Editable Detail Pane
- •Creating the Data Model Object
- •Creating the Detail View List Controller
- •Creating the Detail View Controller
- •Adding an Editable Detail View Controller Instance
- •But There’s One More Thing. . .
- •Breaking the Tape
- •Creating a Simple Storyboard
- •Dynamic Prototype Cells
- •Dynamic Table Content, Storyboard-Style
- •Editing Prototype Cells
- •Good Old Table View Data Source
- •Will It Load?
- •Static Cells
- •Going Static
- •So Long, Good Old Table View Data Source
- •You Say Segue, I Say Segue
- •Creating Segue Navigator
- •Filling the Blank Slate
- •First Transition
- •A Slightly More Useful Task List
- •Viewing Task Details
- •Make More Segues, Please
- •Passing a Task from the List
- •Handling Task Details
- •Passing Back Details
- •Making the List Receive the Details
- •If Only We Could End with a Smooth Transition
- •Split Views and Popovers
- •Creating a SplitView Project
- •The Storyboard Defines the Structure
- •The Code Defines the Functionality
- •The App Delegate
- •The Master View Controller
- •The Detail View Controller
- •Here Come the Presidents
- •Creating Your Own Popover
- •iPad Wrap-Up
- •Getting to Know Your Settings Bundle
- •The AppSettings Application
- •Creating the Project
- •Working with the Settings Bundle
- •Adding a Settings Bundle to Our Project
- •Setting Up the Property List
- •Adding a Text Field Setting
- •Adding an Application Icon
- •Adding a Secure Text Field Setting
- •Adding a Multivalue Field
- •Adding a Toggle Switch Setting
- •Adding the Slider Setting
- •Adding Icons to the Settings Bundle
- •Adding a Child Settings View
- •Reading Settings in Our Application
- •Retrieving User Settings
- •Creating the Main View
- •Updating the Main View Controller
- •Registering Default Values
- •Changing Defaults from Our Application
- •Keeping It Real
- •Beam Me Up, Scotty
- •Your Application’s Sandbox
- •Getting the Documents Directory
- •Getting the tmp Directory
- •File-Saving Strategies
- •Single-File Persistence
- •Multiple-File Persistence
- •Using Property Lists
- •Property List Serialization
- •The First Version of the Persistence Application
- •Creating the Persistence Project
- •Designing the Persistence Application View
- •Editing the Persistence Classes
- •Archiving Model Objects
- •Conforming to NSCoding
- •Implementing NSCopying
- •Archiving and Unarchiving Data Objects
- •The Archiving Application
- •Implementing the BIDFourLines Class
- •Implementing the BIDViewController Class
- •Using iOS’s Embedded SQLite3
- •Creating or Opening the Database
- •Using Bind Variables
- •The SQLite3 Application
- •Linking to the SQLite3 Library
- •Modifying the Persistence View Controller
- •Using Core Data
- •Entities and Managed Objects
- •Key-Value Coding
- •Putting It All in Context
- •Creating New Managed Objects
- •Retrieving Managed Objects
- •The Core Data Application
- •Designing the Data Model
- •Creating the Persistence View and Controller
- •Persistence Rewarded
- •Managing Document Storage with UIDocument
- •Building TinyPix
- •Creating BIDTinyPixDocument
- •Code Master
- •Initial Storyboarding
- •Creating BIDTinyPixView
- •Storyboard Detailing
- •Adding iCloud Support
- •Creating a Provisioning Profile
- •Enabling iCloud Entitlements
- •How to Query
- •Save Where?
- •Storing Preferences on iCloud
- •What We Didn’t Cover
- •Grand Central Dispatch
- •Introducing SlowWorker
- •Threading Basics
- •Units of Work
- •GCD: Low-Level Queueing
- •Becoming a Blockhead
- •Improving SlowWorker
- •Don’t Forget That Main Thread
- •Giving Some Feedback
- •Concurrent Blocks
- •Background Processing
- •Application Life Cycle
- •State-Change Notifications
- •Creating State Lab
- •Exploring Execution States
- •Making Use of Execution State Changes
- •Handling the Inactive State
- •Handling the Background State
- •Removing Resources When Entering the Background
- •Saving State When Entering the Background
- •A Brief Journey to Yesteryear
- •Back to the Background
- •Requesting More Backgrounding Time
- •Grand Central Dispatch, Over and Out
- •Two Views of a Graphical World
- •The Quartz 2D Approach to Drawing
- •Quartz 2D’s Graphics Contexts
- •The Coordinate System
- •Specifying Colors
- •A Bit of Color Theory for Your iOS Device’s Display
- •Other Color Models
- •Color Convenience Methods
- •Drawing Images in Context
- •Drawing Shapes: Polygons, Lines, and Curves
- •The QuartzFun Application
- •Setting Up the QuartzFun Application
- •Creating a Random Color
- •Defining Application Constants
- •Implementing the QuartzFunView Skeleton
- •Creating and Connecting Outlets and Actions
- •Implementing the Action Methods
- •Adding Quartz 2D Drawing Code
- •Drawing the Line
- •Drawing the Rectangle and Ellipse
- •Drawing the Image
- •Optimizing the QuartzFun Application
- •The GLFun Application
- •Setting Up the GLFun Application
- •Creating BIDGLFunView
- •Updating BIDViewController
- •Updating the Nib
- •Finishing GLFun
- •Drawing to a Close
- •Multitouch Terminology
- •The Responder Chain
- •Responding to Events
- •Forwarding an Event: Keeping the Responder Chain Alive
- •The Multitouch Architecture
- •The Four Touch Notification Methods
- •The TouchExplorer Application
- •The Swipes Application
- •Automatic Gesture Recognition
- •Implementing Multiple Swipes
- •Detecting Multiple Taps
- •Detecting Pinches
- •Defining Custom Gestures
- •The CheckPlease Application
- •The CheckPlease Touch Methods
- •Garçon? Check, Please!
- •The Location Manager
- •Setting the Desired Accuracy
- •Setting the Distance Filter
- •Starting the Location Manager
- •Using the Location Manager Wisely
- •The Location Manager Delegate
- •Getting Location Updates
- •Getting Latitude and Longitude Using CLLocation
- •Error Notifications
- •Trying Out Core Location
- •Updating Location Manager
- •Determining Distance Traveled
- •Wherever You Go, There You Are
- •Accelerometer Physics
- •Don’t Forget Rotation
- •Core Motion and the Motion Manager
- •Event-Based Motion
- •Proactive Motion Access
- •Accelerometer Results
- •Detecting Shakes
- •Baked-In Shaking
- •Shake and Break
- •Accelerometer As Directional Controller
- •Rolling Marbles
- •Writing the Ball View
- •Calculating Ball Movement
- •Rolling On
- •Using the Image Picker and UIImagePickerController
- •Implementing the Image Picker Controller Delegate
- •Road Testing the Camera and Library
- •Designing the Interface
- •Implementing the Camera View Controller
- •It’s a Snap!
- •Localization Architecture
- •Strings Files
- •What’s in a Strings File?
- •The Localized String Macro
- •Real-World iOS: Localizing Your Application
- •Setting Up LocalizeMe
- •Trying Out LocalizeMe
- •Localizing the Nib
- •Localizing an Image
- •Generating and Localizing a Strings File
- •Localizing the App Display Name
- •Auf Wiedersehen
- •Apple’s Documentation
- •Mailing Lists
- •Discussion Forums
- •Web Sites
- •Blogs
- •Conferences
- •Follow the Authors
- •Farewell
- •Index
394 |
CHAPTER 11: iPad Considerations |
The split view controller calls this method in the delegate when the left side of the split is about to disappear, and passes in a couple of interesting items: a UIBarButtonItem and a UIPopoverController. The UIPopoverController is already preconfigured to contain whatever was in the left side of the split view, and the UIBarButtonItem is set up to display that very same popover. This means that if our GUI contains a UIToolBar or a
UINavigationItem (the standard toolbar presented by UINavigationController), we just need to add the button item to it in order let the user bring up the navigation view, wrapped inside a popover, with a single tap on the button item.
In this case, since this controller is itself wrapped inside a UINavigationController, we have immediate access to a UINavigationItem where we can place the button item. If our GUI didn’t contain a UINavigationItem or a UIToolbar, we would still have the popover controller passed in, which we could assign to some other element of our GUI so it could pop open the popover for us. We’re also handed the wrapped
UIViewController itself (BIDMasterViewController, in this example) in case we would rather present its contents in some other way.
So, that’s where the popover controller comes from. You may not be too surprised to learn that the next method effectively takes it away:
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
// Called when the view is shown again in the split view, invalidating the button and popover controller.
[self.navigationItem setLeftBarButtonItem:nil animated:YES]; self.masterPopoverController = nil;
}
This method is called when the user switches back to landscape orientation. At that point, the split view controller wants to once again draw the left-side view in a permanent position, so it tells us to get rid of the UIBarButtonItem we were given previously.
That concludes our overview of what Xcode’s Master-Detail Application template gives you. It might be a lot to absorb at a glance, but, ideally, by presenting it a piece at a time, we’ve helped you understand how all the pieces fit together.
Here Come the Presidents
Now that you’ve seen the basic layout of our project, it’s time to fill in the blanks and turn this autogenerated app into something all our own. Start by looking in the book’s source code archive, where the folder 11 – Presidents contains a file called PresidentList.plist. Drag that file into your project’s Presidents folder in Xcode to add it to the project, making sure that the checkbox telling Xcode to copy the file itself is in the on state. This plist file contains information about all the US presidents so far, consisting of just the name and Wikipedia entry URL for each of them.
www.it-ebooks.info
CHAPTER 11: iPad Considerations |
395 |
Now, let’s look at the BIDMasterViewController class and see how we need to modify it to handle the presidential data properly. It’s going to be a simple matter of loading the list of presidents, presenting them in the table view, and passing a URL to the detail view for display. In BIDMasterViewController.h, add the bold line shown here:
#import <UIKit/UIKit.h>
@class BIDDetailViewController;
@interface BIDMasterViewController : UITableViewController
@property (strong, nonatomic) BIDDetailViewController *detailViewController;
@property (strong, nonatomic) NSArray *presidents;
@end
Then switch to BIDMasterViewController.m, where the changes are a little more involved (but still not too bad). Start off by synthesizing the presidents property near the top of the file:
@implementation BIDMasterViewController
@synthesize detailViewController = _detailViewController;
@synthesize presidents;
Next, update the viewDidLoad method, adding a few lines to load the list of presidents:
- (void)viewDidLoad { [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *path = [[NSBundle mainBundle] pathForResource:@"PresidentList" ofType:@"plist"];
NSDictionary *presidentInfo = [NSDictionary dictionaryWithContentsOfFile:path]; self.presidents = [presidentInfo objectForKey:@"presidents"];
self.detailViewController = (BIDDetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionMiddle];
}
Complete the “bookkeeping” part of this class by making the following changes to the viewDidUnload method farther down:
- (void)viewDidUnload { [super viewDidUnload];
//Release any retained subviews of the main view.
//e.g. self.myOutlet = nil;
self.presidents = nil;
}
Now, at some point while looking at this class, you may have been surprised to notice that BIDMasterViewController, despite being a table view controller for displaying a list of items, doesn’t implement any table view delegate or data source methods! Since we’re subclassing from UITableViewController, which implements the required
www.it-ebooks.info
396 |
CHAPTER 11: iPad Considerations |
methods in some basic way, we can get away with that for a while, but now it’s time to start filling in the code so that we can present some data.
Let’s start by letting the table view know how many sections it’s going to have. Add this method at the bottom of the file BIDMasterViewController.m, just before the @end:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1;
}
Technically, this method isn’t really necessary. If it’s not present, the table view will assume 1 as the default number of sections. However, as a point of consistency, including this method makes sense. With the method in place, the number of sections in the table view is explicit and clear.
Next, add the method that tells the table view how many rows to display:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.presidents count];
}
After that, write the the tableView:cellForRowAtIndexPath: method to make each cell display a president’s name:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *Identifier = @"Master List Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier]; if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:Identifier];
}
// Configure the cell.
NSDictionary *president = [self.presidents objectAtIndex:indexPath.row]; cell.textLabel.text = [president objectForKey:@"name"];
return cell;
}
Finally, it’s time to implement tableView:didSelectRowAtIndexPath: to pass the URL to the detail view controller, as follows:
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *president = [self.presidents objectAtIndex:indexPath.row]; NSString *urlString = [president objectForKey:@"url"]; self.detailViewController.detailItem = urlString;
}
That’s all we need to do for BIDMasterViewController. But before we can run this app, we need to make a change to the storyboard. As you will recall from Chapter 10, a UITableView
www.it-ebooks.info
CHAPTER 11: iPad Considerations |
397 |
can be configured to display a fixed set of cells instead of a dynamic collection pulled from the data source. As it turns out, the UITableView in the default storyboard created with this project is configured just that way, so we need to change that.
Select MainStoryboard.storyboard and open the attributes inspector, and then click your way to the UITableView. To do this, find the Master View Controller – Master Scene in the dock list. Open the disclosure triangle to the left of the Master View Controller – Master item, which will reveal the Table View item. Alternatively, you can type table view in the search field at the bottom of the dock. No matter how you got there, select that item.
Once the table view is selected, the attributes inspector will display Table View at the top of the first group of controls. The very first option in that group is Content, which you should now change from Static Cells to Dynamic Prototypes. While you’re there, go ahead and reduce the number of Prototype Cells to 0, as well. We won’t be using the one that’s there by default, and leaving unused, unidentified cell prototypes here will just generate an annoying compiler warning later.
At this point, you can build and run the app. Tap the Master button in the upper-left corner to bring up a popover with a list of presidents (see Figure 11–6). Tap a president’s name to display that president’s Wikipedia page URL in the detail view.
Figure 11–6. Our first run of the Presidents app. Note that we tapped the Master button to bring up the popover. Tap a president’s name, and the link to that president’s Wikipedia entry will be displayed.
www.it-ebooks.info
398 |
CHAPTER 11: iPad Considerations |
Let’s finish this section by making the detail view do something a little more useful with the URL. Start with BIDDetailViewContoller.h, where we’ll add an outlet for a web view to display the Wikipedia page for the selected president. Add the bold line shown here:
#import <UIKit/UIKit.h>
@interface BIDDetailViewController : UIViewController < UISplitViewControllerDelegate>
@property (strong, nonatomic) id detailItem;
@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@end
Then switch to BIDDetailViewController.m, where we have a bit more to do (though really, not too much). Start near the top of the class’s @implementation block, adding synthesis for the webView property:
@synthesize detailItem = _detailItem;
@synthesize detailDescriptionLabel = _detailDescriptionLabel; @synthesize masterPopoverController = _masterPopoverController;
@synthesize webView;
Then scroll down to the configureView method, and add the methods shown in bold here:
- (void)configureView
{
// Update the user interface for the detail item.
NSURL *url = [NSURL URLWithString:self.detailItem]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [self.webView loadRequest:request];
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem description];
}
}
These new lines are all we need to get our web view to load the requested page.
Next, move on down to the splitViewController: willHideViewController:withBarButtonItem:forPopoverController: method, where we’re simply going to give the UIBarButtonItem a more relevant title:
barButtonItem.title = NSLocalizedString(@"Master", @"Master"); barButtonItem.title = NSLocalizedString(@"Presidents", @"Presidents");
All that’s left now is to clean up after ourselves in the viewDidUnload method:
-(void)viewDidUnload {
//Release any retained subviews of the main view.
//e.g. self.myOutlet = nil;
self.webView = nil;
}
Believe it or not, these few edits are all the code we need to write at this point.
www.it-ebooks.info
CHAPTER 11: iPad Considerations |
399 |
The final changes we need to make are in MainStoryboard.storyboard. Open it for editing, find the detail view at the lower right, and start by taking care of the label in the GUI (whose text reads “Detail view content goes here”).
Start by selecting the label. You might find it easiest to select the label in the dock list, in the section labeled Detail View Controller – Detail Scene. You’ll find it quickly by typing label in the dock’s search field.
Once the label is selected, drag the label to the top of the window. Note that the label should run from the left to right blue guideline and fit snugly under the toolbar. This label is being repurposed to show the current URL. But when the application launches, before the user has chosen a president, we want this field to give the user a hint about what to do.
Double-click the label, and change it to Select a President. You should also use the size inspector to make sure that the label’s position is anchored to both the left and right sides, as well as the top edge, and that it allows horizontal resizing so that it can adjust itself between the landscape and portrait orientations (see Figure 11–7).
Figure 11–7. The size inspector, showing the settings for the “Select a President” label
Next, use the library to find a UIWebView and drag it into the space below the label you just moved. After dropping the web view there, use the resize handles to make it fill the rest of the view below the label. Make it go from the left edge to the right edge, and from the blue guideline just below the bottom of the label all the way to the very bottom of the window. Then use the size inspector to anchor the web view to all four edges, and allow it to resize both horizontally and vertically (see Figure 11–8).
www.it-ebooks.info
400 |
CHAPTER 11: iPad Considerations |
Figure 11–8. The size inspector, showing the settings for the web view
We have one last bit of trickery to perform. To hook up the outlet you created, controldrag from the Detail View Controller icon (in the Detail View Controller – Detail section in the dock, just below the First Responder icon) to our new web view (same section, just below the label), and connect the webView outlet. Save your changes, and you’re finished!
Now, you can build and run the app, and it will let you see the Wikipedia entries for each of the presidents. Rotate the display between the two orientations, and you’ll see how the split view controller takes care of everything for you, with a little help from the detail view controller for handling the toolbar item required for showing a popover (just as in the original app before we made our changes).
The final change to make in this section is strictly a cosmetic one. When you run this app in landscape orientation, the heading above the navigation view on the left is still Master. Switch to portrait orientation, tap the Presidents toolbar button, and you’ll see the same heading.
To fix the heading, open MainStoryboard.storyboard, double-click the navigation bar above the table view at the upper right, double-click the text shown there, and change it to Presidents (see Figure 11–9). Save the storyboard, build and run the app, and you should see your change in place.
Figure 11–9. The current state of MainStoryboard.storyboard. We’ve changed the title of the master detail view’s table view to Presidents.
www.it-ebooks.info