2012-02-10 12 views
7

Wchodzę w nowy świat UIPageViewController i jest tam wiele samouczków, jednak wszystkie z nich wydają się tworzyć jeden widok, a następnie po prostu użyć nowych instancji z inną treścią.Jak używać UIPageViewController do ładowania oddzielnych XIB?

Naprawdę chciałbym móc tworzyć wiele XIB-ów, a następnie łączyć je razem z UIPageViewController, ale jest zbyt nowy i nie mogę zrozumieć, jak działa.

+0

Powodzenia? Mam dokładnie to samo pytanie! –

Odpowiedz

4

Cóż, tutaj jest długa odpowiedź, że powinieneś być w stanie skopiować i wkleić. (Ten kod został zaadaptowany z Erica Sadun (https://github.com/erica/iOS-5-Cookbook))

Najpierw utwórz nową klasę typu UIPageViewController. Nazwij to BookController. Teraz wklej następujący kod w pliku .h.

// 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; 

i w pliku .m:

#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; 
} 

Klasa ta może być teraz używany do sterowania każdą książkę, którą tworzy w każdym projekcie, a dla wielu książek w jednym projekcie. Dla każdej książki, stworzyć UIPageViewController delegata z @interface:

@interface NameOfBookController : UIPageViewController <BookControllerDelegate> 

W pliku .m tego delegata obejmują:

// 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]; 
} 

Następnie dodać:

- (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; 
} 

Dla zapisz, ten kod nie jest bezpieczny w pamięci. Jeśli używasz ARC, dodaj swój @autoreleasePool {}; jeśli nie, nie zapomnij o cyklu zachowywania/zwalniania.

Mam nadzieję, że to pomoże!

+3

Jest to sprzeczne z instrukcją klasy UIPageViewController firmy Apple, która mówi: "Aby zmienić zachowanie tej klasy, należy podać źródło danych i delegować." Ta klasa nie jest przeznaczona do subklasyzacji. " –

Powiązane problemy