Changes

An Example iOS 7 UIPageViewController Application

4,831 bytes removed, 21:05, 14 April 2014
Running the UIPageViewController Application
{
NSString *contentString = [[NSString alloc]
initWithFormat:@"<html><head></head><body><br><h1>Chapter %d</h1><p>This is the page %d of content displayed using UIPageViewController in iOS 7.</p></body></html>", i, i]; [pageStrings addObject:contentString]; } _pageContent = [[NSArray alloc] initWithArray:pageStrings];}..- (void)viewDidLoad{ [super viewDidLoad]; [self createContentPages];}</pre> The application now has a content view controller and a data model from which the content of each page will be extracted by the data source methods. The next logical step, therefore, is to implement those data source methods. As previously outlined in Implementing a Page based iOS 7 Application using UIPageViewController, instances of the UIPageViewController class need a data source. This takes the form of two methods, one of which is required to return the view controller to be displayed after the currently displayed view controller, and the other the view controller to be displayed before the current view controller. Since the PageAppViewController is going to act as the data source for the page view controller object, these two methods, together with two convenience methods (which we will borrow from the Xcode Page-based Application template) will need to be added to the PageAppViewController.m file. Begin by adding the two convenience functions:  <pre>#import "PageAppViewController.h" @interface PageAppViewController () @end @implementation PageAppViewController  - (ContentViewController *)viewControllerAtIndex:(NSUInteger)index{ // Return the data view controller for the given index. if (([self.pageContent count] == 0) || (index >= [self.pageContent count])) { return nil; }  // Create a new view controller and pass suitable data. /* ContentViewController *dataViewController = [[ContentViewController alloc] init]; */  UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];  ContentViewController *dataViewController = [storyboard instantiateViewControllerWithIdentifier:@"contentView"];  dataViewController.dataObject = _pageContent[index]; return dataViewController;} - (NSUInteger)indexOfViewController:(ContentViewController *)viewController{ return [_pageContent indexOfObject:viewController.dataObject];}..@end</pre> The viewControllerAtIndex method begins by checking to see if the page being requested is outside the bounds of available pages by checking if the index reference is zero (the user cannot page back beyond the first page) or greater than the number of items in the pageContent array. In the event that the index value is valid, a new instance of the ContentViewController class is created and the dataObject property set to the contents of the corresponding item in the pageContent array of HTML strings.  Since the view controller is stored in the storyboard file, the following code is used to get a reference to the storyboard and to create a new ContentViewController instance: <pre>UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:[NSBundle mainBundle]]; ContentViewController *dataViewController = [storyboard instantiateViewControllerWithIdentifier:@"contentView"];</pre> The indexOfViewController method is passed a viewController object and is expected to return the index value of the controller. It does this by extracting the dataObject property of the view controller and finding the index of the matching element in the pageContent array. All that remains to be implemented as far as the data source is concerned are the two data source protocol methods which, in turn, make use of the two convenience methods to return the view controllers before and after the current view controller: <pre>- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{ NSUInteger index = [self indexOfViewController: (ContentViewController *)viewController]; if ((index == 0) || (index == NSNotFound)) { return nil; }  index--; return [self viewControllerAtIndex:index];} - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{ NSUInteger index = [self indexOfViewController: (ContentViewController *)viewController]; if (index == NSNotFound) { return nil; }  index++; if (index == [self.pageContent count]) { return nil; } return [self viewControllerAtIndex:index];}</pre> With the data source implemented, the next step is to create and initialize an instance of the UIPageViewController class.   == Running the UIPageViewController Application ==
Click on the Run button to compile and launch the application in the iOS iPhone Simulator or on a physical device. Once loaded, the first content page should appear. A right to left gesture motion on the screen will cause the page to transition to the second page of content and reversing the gesture direction will page backwards:
[[Image:ios_7_page_app_running.png|An iOS 7 example UIPageViewController app running]]
Figure 28-2