页面控制器

时间:2009-11-08 13:58:53

标签: iphone uipagecontrol

我在从数组中删除未使用的页面时遇到问题:

NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < [descriptionsList count]; i++) {
        [controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
[controllers release];
[self loadScrollViewWithPage:0];
[self loadScrollViewWithPage:1];

我正在添加以下对象:

- (void)loadScrollViewWithPage:(int)page {
    if (page < 0) return;
    if (page >= [descriptionsList count]) return;
    // replace the placeholder if necessary
    DetailsView *controller = [viewControllers objectAtIndex:page];
    if ((NSNull *)controller == [NSNull null]) {
        controller = [[DetailsView alloc] initWithElement:[descriptionsList objectAtIndex:page]
                                                 andFrame:CGRectMake(320*page, 0, 320, 420)];
        [viewControllers replaceObjectAtIndex:page withObject:controller];
        [controller release];
    }

    // add the controller's view to the scroll view
    if (nil == controller.superview) {
        [scrollView addSubview:controller];
    }
}

我正在使用它来删除和创建页面:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    pageControlUsed = NO;

    //load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
    for (unsigned i = 0; i < [descriptionsList count]; i++) {
        if (i < pageController.currentPage - 1 || i > pageController.currentPage + 1) {
            if ([viewControllers objectAtIndex:i] != nil) {
                [[viewControllers objectAtIndex:i] release];
                [viewControllers replaceObjectAtIndex:i withObject:[NSNull null]];
            }
        }
        else {
            [self loadScrollViewWithPage:i];
        }
    }
}

当我想要查看第3页时,我的应用程序崩溃了很长时间。有关应该如何做的任何建议?感谢。

3 个答案:

答案 0 :(得分:2)

有几个问题:

  • NSArrays无法存储'nil'对象,因此您对!= nil的检查将始终成功,因此您不需要它
  • 你绝对不应该释放数组中的对象;您没有相应的-retain消息,无论如何,该数组将自动保留放入其中的对象,并在删除它们时释放它们
  • 你的命名有点令人困惑。你有一个名为viewControllers的数组,以及一个被反对的被叫控制器,但这两个看起来都是视图(因为你是initWithFrame它们。

答案 1 :(得分:1)

这一行:

if ([viewControllers objectAtIndex:i] != nil)

将始终计算为TRUE,因为数组中填充的NSNULL对象的值不为nil。即使存在索引处存在视图,该块也会执行。此块将使用NSNull个对象填充整个数组,从而消除所有视图。对视图的任何后续调用都将崩溃。

我觉得你的设计很糟糕。您不应该将视图放入数组中。相反,您需要在数组中包含 数据 ,然后根据在任何给定时间显示的数据填充可重用视图。看看'UITable'如何通过可重复使用的'UITableViewCells'显示自己。

答案 2 :(得分:-1)

这种延迟加载的方法实际上是从一本好书中得到的,但是样本的视图非常简单,并且没有发布它们。页面初始化是在scrollViewDidScroll方法中进行的,该方法在我的内容设备上完全混乱:一张照片和两个文本。而使用的内存正在崩溃我的应用程序,这就是为什么我想继续只加载3页。这是更新的代码,但我不能释放对象,也不能从视图中删除,所以我得到重复。

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {

    for (unsigned i = 0; i < [descriptionsList count]; i++) {
        if (i < pageController.currentPage - 1 || i > pageController.currentPage + 1) {
            DetailsView *controller = [viewControllers objectAtIndex:i];
            if ((NSNull *)controller != [NSNull null]) {
                if (nil != controller.superview) {
                    NSLog(@"remove from superview %d", i);
                    //[controller.superview removeFromSuperview];
                }
                [viewControllers removeObjectAtIndex:i];
                [viewControllers insertObject:[NSNull null] atIndex:i];
                //[viewControllers replaceObjectAtIndex:i withObject:[NSNull null]];
            }
        }
        else {
            NSLog(@"allocating %d", i);
            [self loadScrollViewWithPage:i];
        }
    }
}

那么,如果我只使用2个可重复使用的视图,我是否可以实时创建我的视图而不会闪烁?我看过一个包含2个视图的样本,但是说内容必须存在,而且我不确定在内存中保留15个png有多好。