How to use UIPageViewController to load individual XIB?

I delve into the new world of UIPageViewControllers and there are many tutorials, but they all seem to create one view, and then just use new instances of it with different content.

I would really like to create several XIBs and then just link them together with the UIPageViewController, but this is too new and I can’t understand how it works.

+7
source share
2 answers

Well, here is a long answer that you can copy and paste. (This code was adapted from Erica Sadun (https://github.com/erica/iOS-5-Cookbook))

First create a new class like UIPageViewController. Name it BookController. Now paste the following code into your .h file.

// Used for storing the most recent book page used #define DEFAULTS_BOOKPAGE @"BookControllerMostRecentPage" @protocol BookControllerDelegate <NSObject> - (id) viewControllerForPage: (int) pageNumber; @optional - (void) bookControllerDidTurnToPage: (NSNumber *) pageNumber; @end @interface BookController : UIPageViewController <UIPageViewControllerDelegate, UIPageViewControllerDataSource> + (id) bookWithDelegate: (id) theDelegate; + (id) rotatableViewController; - (void) moveToPage: (uint) requestedPage; - (int) currentPage; @property (assign) id <BookControllerDelegate> bookDelegate; @property (nonatomic, assign) uint pageNumber; 

and in your .m file:

 #define IS_IPHONE ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) #define SAFE_ADD(_Array_, _Object_) {if (_Object_ && [_Array_ isKindOfClass:[NSMutableArray class]]) [pageControllers addObject:_Object_];} #define SAFE_PERFORM_WITH_ARG(THE_OBJECT, THE_SELECTOR, THE_ARG) (([THE_OBJECT respondsToSelector:THE_SELECTOR]) ? [THE_OBJECT performSelector:THE_SELECTOR withObject:THE_ARG] : nil) #pragma Utility Class - VC that Rotates @interface RotatableVC : UIViewController @end @implementation RotatableVC - (void) loadView { [super loadView]; self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; self.view.backgroundColor = [UIColor whiteColor]; } - (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return YES; } @end #pragma Book Controller @implementation BookController @synthesize bookDelegate, pageNumber; #pragma mark Debug / Utility - (int) currentPage { int pageCheck = ((UIViewController *)[self.viewControllers objectAtIndex:0]).view.tag; return pageCheck; } #pragma mark Page Handling // Update if you'd rather use some other decision style - (BOOL) useSideBySide: (UIInterfaceOrientation) orientation { BOOL isLandscape = UIInterfaceOrientationIsLandscape(orientation); return isLandscape; } // Store the new page and update the delegate - (void) updatePageTo: (uint) newPageNumber { pageNumber = newPageNumber; [[NSUserDefaults standardUserDefaults] setInteger:pageNumber forKey:DEFAULTS_BOOKPAGE]; [[NSUserDefaults standardUserDefaults] synchronize]; SAFE_PERFORM_WITH_ARG(bookDelegate, @selector(bookControllerDidTurnToPage:), [NSNumber numberWithInt:pageNumber]); } // Request controller from delegate - (UIViewController *) controllerAtPage: (int) aPageNumber { if (bookDelegate && [bookDelegate respondsToSelector:@selector(viewControllerForPage:)]) { UIViewController *controller = [bookDelegate viewControllerForPage:aPageNumber]; controller.view.tag = aPageNumber; return controller; } return nil; } // Update interface to the given page - (void) fetchControllersForPage: (uint) requestedPage orientation: (UIInterfaceOrientation) orientation { BOOL sideBySide = [self useSideBySide:orientation]; int numberOfPagesNeeded = sideBySide ? 2 : 1; int currentCount = self.viewControllers.count; uint leftPage = requestedPage; if (sideBySide && (leftPage % 2)) leftPage--; // Only check against current page when count is appropriate if (currentCount && (currentCount == numberOfPagesNeeded)) { if (pageNumber == requestedPage) return; if (pageNumber == leftPage) return; } // Decide the prevailing direction by checking the new page against the old UIPageViewControllerNavigationDirection direction = (requestedPage > pageNumber) ? UIPageViewControllerNavigationDirectionForward : UIPageViewControllerNavigationDirectionReverse; [self updatePageTo:requestedPage]; // Update the controllers NSMutableArray *pageControllers = [NSMutableArray array]; SAFE_ADD(pageControllers, [self controllerAtPage:leftPage]); if (sideBySide) SAFE_ADD(pageControllers, [self controllerAtPage:leftPage + 1]); [self setViewControllers:pageControllers direction: direction animated:YES completion:nil]; } // Entry point for external move request - (void) moveToPage: (uint) requestedPage { [self fetchControllersForPage:requestedPage orientation:(UIInterfaceOrientation)[UIDevice currentDevice].orientation]; } #pragma mark Data Source - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { [self updatePageTo:pageNumber + 1]; return [self controllerAtPage:(viewController.view.tag + 1)]; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { [self updatePageTo:pageNumber - 1]; return [self controllerAtPage:(viewController.view.tag - 1)]; } #pragma mark Delegate - (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation { NSUInteger indexOfCurrentViewController = 0; if (self.viewControllers.count) indexOfCurrentViewController = ((UIViewController *)[self.viewControllers objectAtIndex:0]).view.tag; [self fetchControllersForPage:indexOfCurrentViewController orientation:orientation]; BOOL sideBySide = [self useSideBySide:orientation]; self.doubleSided = sideBySide; UIPageViewControllerSpineLocation spineLocation = sideBySide ? UIPageViewControllerSpineLocationMid : UIPageViewControllerSpineLocationMin; return spineLocation; } -(void)dealloc{ self.bookDelegate = nil; } #pragma mark Class utility routines // Return a UIViewController that knows how to rotate + (id) rotatableViewController { UIViewController *vc = [[RotatableVC alloc] init]; return vc; } // Return a new book + (id) bookWithDelegate: (id) theDelegate { BookController *bc = [[BookController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil]; bc.dataSource = bc; bc.delegate = bc; bc.bookDelegate = theDelegate; return bc; } 

This class can now be used to manage any book that you create in any project, and for several books in one project. For each book, create a UIPageViewController delegate with @interface:

 @interface NameOfBookController : UIPageViewController <BookControllerDelegate> 

In this delegate's .m file, include:

 // Implement loadView to create a view hierarchy programmatically, without using a nib. - (void)loadView { [super loadView]; CGRect appRect = [[UIScreen mainScreen] applicationFrame]; self.view = [[UIView alloc] initWithFrame: appRect]; self.view.backgroundColor = [UIColor whiteColor]; self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; // Establish the page view controller bookController = [BookController bookWithDelegate:self]; bookController.view.frame = (CGRect){.size = appRect.size}; } // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { // Add the child controller, and set it to the first page [self.view addSubview:bookController.view]; [self addChildViewController:bookController]; [bookController didMoveToParentViewController:self]; } 

Then add:

 - (id) viewControllerForPage: (int) pageNumber { // Establish a new controller UIViewController *controller; switch (pageNumber) { case 0: view1 = [[FirstViewController alloc] init]; view1.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; controller = view1; //rinse and repeat with each new view controller break; case 1: //etc. break; default: return nil; break; } return controller; } 

For writing, this code is not memory safe. If you use ARC, add to your @autoreleasePool {}; if not, don't forget about your save / release cycle.

Hope this helps!

+4
source

This article shows how to create an application using the UIPageViewController with custom view controllers for each page: http://www.informit.com/articles/article.aspx?p=1760500&seqNum=6

0
source

All Articles