使用UIScrollView进行分页

时间:2012-10-16 08:50:44

标签: iphone objective-c ios

我想创建一个类似Paging with UIScrollView in the tutorial的scrollView。唯一不同的是在我的应用程序中我将.xib文件添加到UIscrollView而不是UIImageView,我从后端部分获取数据而不是静态设置它们。

我发现需要时间的线(它实际上将图像加载到另一个scrollView):

[self.offerView loadVisiblePages];

这就是那里发生的事情:

@implementation OfferUIView

- (void)initialization {
    NSInteger pageCount = self.pageImages.count;

    // Set up the array to hold the views for each page
    self.pageViews = [[NSMutableArray alloc] init];
    for (NSInteger i = 0; i < pageCount; ++i) {
        [self.pageViews addObject:[NSNull null]];
    }

    CGSize pagesScrollViewSize = self.scrollView.frame.size;
    self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * 3, pagesScrollViewSize.height);
}

- (void)loadVisiblePages {
    [self initialization];

    // First, determine which page is currently visible
    CGFloat pageWidth = self.scrollView.frame.size.width;
    NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));

    // Work out which pages we want to load
    NSInteger firstPage = page - 1;
    NSInteger lastPage = page + 1;

    // Purge anything before the first page
    for (NSInteger i=0; i<firstPage; i++) {
        [self purgePage:i];
    }
    for (NSInteger i=firstPage; i<=lastPage; i++) {
        [self loadPage:i];
    }
    for (NSInteger i=lastPage+1; i<self.pageImages.count; i++) {
        [self purgePage:i];
    }
}

我的问题是,当我第一次运行应用程序时,加载图像速度太慢。你能救我吗?

这是.h文件:

@interface ViewController2 : UIViewController {
@private
    UIScrollView *scrollView;
}

@property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
@property (nonatomic, strong) PFLogInViewController *login;

@end

.m文件:

@interface ViewController2 ()
@property (nonatomic, strong) NSMutableDictionary *pageImages;
@property (nonatomic, strong) NSMutableArray *companies;
@property (nonatomic, strong) NSMutableArray *offers;
@property (nonatomic, strong) NSMutableArray *pageViews;
@property (nonatomic, strong) OfferUIView *offerView;
@property (nonatomic, assign) NSString *address;

- (void)loadVisiblePages;
- (void)loadPage:(NSInteger)page;
- (void)purgePage:(NSInteger)page;

@end

@implementation ViewController2

@synthesize scrollView = _scrollView;
@synthesize offerView = _offerView;

@synthesize pageImages = _pageImages;
@synthesize companies = _companies;
@synthesize offers = _offers;
@synthesize pageViews = _pageViews;
- (void)loadVisiblePages {
    // First, determine which page is currently visible

    CGFloat pageWidth = self.scrollView.frame.size.height;
    NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.y * 2.0f + pageWidth) / (pageWidth * 2.0f));

    // Work out which pages we want to load
    NSInteger firstPage = page - 1;
    NSInteger lastPage = page + 1;

    // Purge anything before the first page
    for (NSInteger i=0; i<firstPage; i++) {
        [self purgePage:i];
    }
    for (NSInteger i=firstPage; i<=lastPage; i++) {
        [self loadPage:i];
    }
    for (NSInteger i=lastPage+1; i<self.pageImages.count; i++) {
        [self purgePage:i];
    }
}

- (void)loadPage:(NSInteger)page {
    if (page < 0 || page >= self.pageImages.count) {
        // If it's outside the range of what we have to display, then do nothing
        return;
    }
    // Load an individual page, first seeing if we've already loaded it
    UIView *pageView = [self.pageViews objectAtIndex:page];
    if ((NSNull*)pageView == [NSNull null]) {

        CGRect frame = self.scrollView.bounds;
        frame.origin.x = 0.0f;
        frame.origin.y = frame.size.height * page;

        NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"OfferView" owner:self options:nil];
        self.offerView = [views objectAtIndex:0];
        self.offerView.contentMode = UIViewContentModeScaleAspectFit;
        self.offerView.frame = frame;
        [self.scrollView addSubview:self.offerView];
        [self.pageViews replaceObjectAtIndex:page withObject:self.offerView];

        self.offerView.pageId = 1;

        Company *company = [self.companies objectAtIndex:page];
        self.offerView.labelCompany.text = company.name;
        self.offerView.companyAddress = company.address;


        Offer *offer = [self.offers objectAtIndex:page];
        NSMutableArray *imageArray = [self.pageImages objectForKey:offer.objectId];
        self.offerView.pageImages = imageArray;
        self.offerView.offerId = offer.objectId;
        [self.offerView loadVisiblePages];

        self.offerView.labelOffer.text = @"Vid köp för minst";
        self.offerView.labelOffer.text =[[self.offerView.labelOffer.text stringByAppendingFormat:@" %i", offer.offer] stringByAppendingString:@"kr."];

        [self.offerView.labelDiscount setText: [[NSString stringWithFormat:@"%i", offer.discount] stringByAppendingString:@":-"]];

        double deadline = [offer.deadline timeIntervalSinceNow];
        double createdAt = [offer.createdAt timeIntervalSinceNow];
        double difference = deadline - createdAt;

        NSNumber *theDouble = [NSNumber numberWithDouble:difference];
        int inputSeconds = [theDouble intValue];
        int hours =  inputSeconds / 3600;
        int minutes = ( inputSeconds - hours * 3600 ) / 60;
        //int seconds = inputSeconds - hours * 3600 - minutes * 60;
        NSString *theTime = [NSString stringWithFormat:@"%dh %dm", hours, minutes];
        [self.offerView.labelDeadline setText:theTime];
    }
}

- (void)purgePage:(NSInteger)page {
    if (page < 0 || page >= self.pageImages.count) {
        // If it's outside the range of what we have to display, then do nothing
        return;
    }

    // Remove a page from the scroll view and reset the container array
    UIView *pageView = [self.pageViews objectAtIndex:page];
    if ((NSNull*)pageView != [NSNull null]) {
        [pageView removeFromSuperview];
        [self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // Set up the image we want to scroll and add it to the scroll view
    [self loadDataFromParse];

    NSInteger pageCount = self.pageImages.count;

    // Set up the array to hold the views for each page
    self.pageViews = [[NSMutableArray alloc] init];
    for (NSInteger i = 0; i < pageCount; ++i) {
        [self.pageViews addObject:[NSNull null]];
    }
    printf("%s\n", [@"ViewDidLoad" UTF8String]);
}

- (void)loadDataFromParse {
    self.pageImages = [[NSMutableDictionary alloc] init];
    self.companies = [[NSMutableArray alloc] init];
    self.offers = [[NSMutableArray alloc] init];

    PFQuery *companyQuery = [PFQuery queryWithClassName:@"Company"];
    NSArray *companyArray = [companyQuery findObjects];

    NSArray *offerArray;
    PFQuery *offerQuery = [PFQuery queryWithClassName:@"Offer"];

    NSArray *imageArray;
    PFQuery *imageQuery = [PFQuery queryWithClassName:@"Image"];

    for (NSInteger i=0; i<companyArray.count; i++) {
        PFObject *fetchedCompany = [companyArray objectAtIndex:i];
        Company *company = [[Company alloc] init];
        company.name = [fetchedCompany objectForKey:@"name"];
        company.address = [fetchedCompany objectForKey:@"address"];
        [offerQuery whereKey:@"company" equalTo:fetchedCompany];
        offerArray = [offerQuery findObjects];

        for (NSInteger j=0; j<offerArray.count; j++) {
            PFObject *fetchedOffer = [offerArray objectAtIndex:j];
            Offer *offer = [[Offer alloc] init];
            offer.objectId = [fetchedOffer valueForKey:@"objectId"];
            offer.offer = [[fetchedOffer objectForKey:@"offer"]integerValue];
            offer.discount = [[fetchedOffer objectForKey:@"discount"]integerValue];
            offer.deadline = [fetchedOffer objectForKey:@"deadline"];
            offer.createdAt = [fetchedOffer objectForKey:@"createdAt"];

            [imageQuery whereKey:@"offer" equalTo:fetchedOffer];
            imageArray = [imageQuery findObjects];

            NSMutableArray *array = [[NSMutableArray alloc] init];
            for (NSInteger k=0; k<imageArray.count; k++) {
                PFObject *fetchedimage = [imageArray objectAtIndex:k];
                [array addObject:fetchedimage];
            }
            [self.pageImages setObject:array forKey:offer.objectId];
            [self.offers addObject:offer];
            [self.companies addObject:company];
        }
    }
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // Set up the content size of the scroll view
    CGSize pagesScrollViewSize = self.scrollView.frame.size;

    //self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageImages.count, pagesScrollViewSize.height);

    self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width, pagesScrollViewSize.height * self.pageImages.count);

    // Load the initial set of pages that are on screen
    [self loadVisiblePages];

    printf("%s\n", [@"ViewWillAppear" UTF8String]);
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    self.offers = nil;
    self.companies = nil;
    self.pageImages = nil;
    self.pageViews = nil;
    self.scrollView = nil;
    self.offerView = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    // Load the pages which are now on screen
    [self loadVisiblePages];
}

3 个答案:

答案 0 :(得分:0)

下载SMPageControl示例..,它可能对你有帮助..

答案 1 :(得分:0)

在加载某些数据的情况下需要花费太多时间,您应该将工作卸载到后台线程。您尝试使用GCD吗?

例如,你会这样做:

dispatch_queue_t preloadQueue = dispatch_queue_create("preload queue", nil);
    dispatch_async(preloadQueue, ^{
        // do the heavy task here
        dispatch_async(dispatch_get_main_queue(), ^{
        // set-up all the ui components that are required to be set on the main thread
        });
    });

同时使用InstrumentsTime Profiling Tool一起确定哪条指令需要一段时间。

答案 2 :(得分:0)

为了提高您的响应能力,我建议:

  • 首先加载缩略图,然后在背景中加载实际图像。
  • 回收图像并在内存中保留最多3个。
  • 加载UIImageViews并加载UIImages以下方法,以避免iOS缓存图片(在内存中进行手动缓存):

    + (UIImage *)imageWithContentsOfFile:(NSString *)path

  • 如果加载缩略图是不可接受的,而且您的图片非常大,我会将它们平铺。

您需要检查WWDC 2010中的Designing apps with Scrollviews(需要登录)以及Apple的以下示例:PhotoScroller&amp; ScrollViewSuite。还有一个来自WWDC 2009的有趣视频,名为掌握iPhone中的滚动视图,其中包括以UITableView单元回收方式回收图像,但我找不到它。