0

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

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 页时,我的应用程序崩溃了。有关如何完成此操作的任何建议?谢谢。

4

3 回答 3

2

几个问题:

  • NSArrays 不能存储 'nil' 对象,因此您对 != nil 的检查将始终成功,因此您不需要它
  • 您绝对不应该释放数组中的对象;您没有相应的 -retain 消息,无论如何,数组将自动保留放入其中的对象,并在删除时释放它们
  • 你的命名法有点混乱。您有一个名为 viewControllers 的数组和一个名为控制器的对象,但它们似乎都是视图(因为您正在初始化它们。
于 2009-11-08T14:53:39.030 回答
1

这一行:

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

将始终评估为 TRUE,因为该数组填充了不评估为 nil 的 NSNULL 对象。即使索引中存储了视图,该块也会执行。这个块将用对象填充你的整个数组NSNull,消除你所有的视图。对视图的任何后续调用都将崩溃。

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

于 2009-11-08T17:52:48.177 回答
-1

这种延迟加载的方法实际上我是从一本好书中得到的,但是该示例具有非常非常简单的视图,并且没有发布它们。页面初始化是在 scrollViewDidScroll 方法中进行的,我的内容在设备上完全是一团糟:一张照片和 2 条文本。使用的内存使我的应用程序崩溃,这就是为什么我只想保持加载 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 有多好。

于 2009-11-08T20:41:20.700 回答