views:

1504

answers:

3

Ok, so I am trying to a pagescrollView with two views each with a different view controller so I can work on each different view. I got apple's sample code and it seems that they created a lot of different view "lazily as they said" how can this code be altered so that I can have the first page be one view controller and the second page be another view controller?

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    // view controllers are created lazily
    // in the meantime, load the array with placeholders which will be replaced on demand
    NSMutableArray *controllers = [[NSMutableArray alloc] init];
    for (unsigned i = 0; i // a page is the width of the scroll view
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.scrollsToTop = NO;
scrollView.delegate = self;

pageControl.numberOfPages = kNumberOfPages;
pageControl.currentPage = 0;

// pages are created on demand
// load the visible page
// load the page on either side to avoid flashes when the user starts scrolling
[self loadScrollViewWithPage:0];
[self loadScrollViewWithPage:1];

}

  • (void)loadScrollViewWithPage:(int)page { if (page < 0) return; if (page >= kNumberOfPages) return;

    // replace the placeholder if necessary MyViewController *controller = [viewControllers objectAtIndex:page]; if ((NSNull *)controller == [NSNull null]) { controller = [[MyViewController alloc] initWithPageNumber:page]; [viewControllers replaceObjectAtIndex:page withObject:controller]; [controller release]; }

    // add the controller's view to the scroll view if (nil == controller.view.superview) { CGRect frame = scrollView.frame; frame.origin.x = frame.size.width * page; frame.origin.y = 0; controller.view.frame = frame; [scrollView addSubview:controller.view]; } }

  • (void)scrollViewDidScroll:(UIScrollView *)sender { // We don't want a "feedback loop" between the UIPageControl and the scroll delegate in // which a scroll event generated from the user hitting the page control triggers updates from // the delegate method. We use a boolean to disable the delegate logic when the page control is used. if (pageControlUsed) { // do nothing - the scroll was initiated from the page control, not the user dragging return; } // Switch the indicator when more than 50% of the previous/next page is visible CGFloat pageWidth = scrollView.frame.size.width; int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; pageControl.currentPage = page;

    // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling) [self loadScrollViewWithPage:page - 1]; [self loadScrollViewWithPage:page]; [self loadScrollViewWithPage:page + 1];

    // A possible optimization would be to unload the views+controllers which are no longer visible }

// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { pageControlUsed = NO; }

  • (IBAction)changePage:(id)sender { int page = pageControl.currentPage; // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling) [self loadScrollViewWithPage:page - 1]; [self loadScrollViewWithPage:page]; [self loadScrollViewWithPage:page + 1]; // update the scroll view to the appropriate page CGRect frame = scrollView.frame; frame.origin.x = frame.size.width * page; frame.origin.y = 0; [scrollView scrollRectToVisible:frame animated:YES]; // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above. pageControlUsed = YES; }

Thanks if anyone knows how to do this.

+3  A: 

To load the pages with different view controllers all you have to change is this segment of code

MyViewController *controller = [viewControllers objectAtIndex:page]; 
if ((NSNull *)controller == [NSNull null]) 
{ controller = [[MyViewController alloc] initWithPageNumber:page]; 
[viewControllers replaceObjectAtIndex:page withObject:controller];
 [controller release]; 
}

to initialize each view controller to the one you want instead of the same one each time, so the code would look something like

 if(page==0)
{
 MyViewControllerZero *controller = [viewControllers objectAtIndex:page]; 
    if ((NSNull *)controller == [NSNull null]) 
    { controller = [[MyViewControllerZero alloc] initWithPageNumber:page]; 
    [viewControllers replaceObjectAtIndex:page withObject:controller];
     [controller release]; 
    }
}
  if(page==1)
{
 MyViewControllerOne *controller = [viewControllers objectAtIndex:page]; 
    if ((NSNull *)controller == [NSNull null]) 
    { controller = [[MyViewControllerOne alloc] initWithPageNumber:page]; 
    [viewControllers replaceObjectAtIndex:page withObject:controller];
     [controller release]; 
    }
}
//and so on ...
Daniel
A: 

i tried to do this - project compile with no errors, but application crashes :( where i make mistake? here is my code:

import "AppDelegate.h"

import "MyViewController.h"

import "MyViewControllerZero.h"

import "MyViewControllerOne.h"

static NSUInteger kNumberOfPages = 2;

@interface AppDelegate (PrivateMethods)

  • (void)loadScrollViewWithPage:(int)page;
  • (void)scrollViewDidScroll:(UIScrollView *)sender;

@end

@implementation AppDelegate

@synthesize window, scrollView, pageControl, viewControllers;

  • (void)dealloc { [viewControllers release]; [scrollView release]; [pageControl release]; [window release]; [super dealloc]; }

  • (void)applicationDidFinishLaunching:(UIApplication *)application { // view controllers are created lazily // in the meantime, load the array with placeholders which will be replaced on demand NSMutableArray *controllers = [[NSMutableArray alloc] init]; for (unsigned i = 0; i < kNumberOfPages; i++) { [controllers addObject:[NSNull null]]; } self.viewControllers = controllers; [controllers release];

    // a page is the width of the scroll view scrollView.pagingEnabled = YES; scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height); scrollView.showsHorizontalScrollIndicator = NO; scrollView.showsVerticalScrollIndicator = NO; scrollView.scrollsToTop = NO; scrollView.delegate = self;

    pageControl.numberOfPages = kNumberOfPages; pageControl.currentPage = 0;

    // pages are created on demand // load the visible page // load the page on either side to avoid flashes when the user starts scrolling [self loadScrollViewWithPage:0]; [self loadScrollViewWithPage:1]; }

  • (void)loadScrollViewWithPage:(int)page { if (page < 0) return; if (page >= kNumberOfPages) return;

    // replace the placeholder if necessary if(page==0) { MyViewControllerZero *controller = [viewControllers objectAtIndex:page]; if ((NSNull *)controller == [NSNull null]) { controller = [[MyViewControllerZero alloc] initWithPageNumber:page]; [viewControllers replaceObjectAtIndex:page withObject:controller]; [controller release]; } } if(page==1) { MyViewControllerOne *controller = [viewControllers objectAtIndex:page]; if ((NSNull *)controller == [NSNull null]) { controller = [[MyViewControllerOne alloc] initWithPageNumber:page]; [viewControllers replaceObjectAtIndex:page withObject:controller]; [controller release]; } }

    /* // add the controller's view to the scroll view if (nil == controller.view.superview) { CGRect frame = scrollView.frame; frame.origin.x = frame.size.width * page; frame.origin.y = 0; controller.view.frame = frame; [scrollView addSubview:controller.view]; }*/ }

  • (void)scrollViewDidScroll:(UIScrollView *)sender { // We don't want a "feedback loop" between the UIPageControl and the scroll delegate in // which a scroll event generated from the user hitting the page control triggers updates from // the delegate method. We use a boolean to disable the delegate logic when the page control is used. if (pageControlUsed) { // do nothing - the scroll was initiated from the page control, not the user dragging return; }

    // Switch the indicator when more than 50% of the previous/next page is visible CGFloat pageWidth = scrollView.frame.size.width; int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; pageControl.currentPage = page;

    // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling) [self loadScrollViewWithPage:page - 1]; [self loadScrollViewWithPage:page]; [self loadScrollViewWithPage:page + 1];

    // A possible optimization would be to unload the views+controllers which are no longer visible }

// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { pageControlUsed = NO; }

// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { pageControlUsed = NO; }

  • (IBAction)changePage:(id)sender { int page = pageControl.currentPage;

    // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling) [self loadScrollViewWithPage:page - 1]; [self loadScrollViewWithPage:page]; [self loadScrollViewWithPage:page + 1];

    // update the scroll view to the appropriate page CGRect frame = scrollView.frame; frame.origin.x = frame.size.width * page; frame.origin.y = 0; [scrollView scrollRectToVisible:frame animated:YES];

    // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above. pageControlUsed = YES; }

@end

Sergey
A: 

Thanks! It works

Mark