在scrollview中分页和重用视图

时间:2012-10-24 19:44:00

标签: ios uiview uiscrollview pagination lazy-loading

我必须在滚动视图中显示大约100页,每页包含8个图像视图和8个标签..图像视图的图像应该懒惰加载。我创建的示例懒洋洋地加载图像,分页也很好,但我加载所有100页,每页包含8个图像视图和8个标签..在模拟器上工作正常,但我没有在设备上测试,因为我很害怕看到它崩溃,因为我一次加载这么多的视图。任何人都可以帮助我或引导我一些样本,它可以帮助我重复使用我的观点以及我可以执行延迟加载的图像视图吗?

4 个答案:

答案 0 :(得分:4)

我建议UIPageViewControllerthis is a good tutorial如何实施它。

所以我们的想法是你有一个控制器在页面上显示你的所有图像和标签,所以当你转到下一页时,你只需启动另一个控制器并设置图像,你也可以从内存中删除上一页。每个页面都由页面控制器的实例表示,UIPageViewController负责。如果您不想这样做,则不必进行页面卷曲动画。

当然,您可以在滚动视图中计算页面上每个项目的位置,并使用UIScrollView的分页移动项目并加载其他图像,但如果您有数百页,为什么不使用{{ 1}}?

顺便说一句,您甚至不需要教程,只需从iOS模板创建UIPageViewController,然后将代码移至Page Based ApplicationModel Controller

答案 1 :(得分:2)

查看帖子UIScrollView and lazy loading,描述如何在UIScrollView中延迟加载图片。

这正是您正在寻找的UIScrollView延迟加载的逐步介绍。

这个想法是:你在内存中保留3个视图:当前视图,前一个视图和下一个视图;所以你可以毫不拖延地移动到下一个或前一个。当您移动到一个新视图时,您将加载上一个视图和下一个视图(如果需要)。如果您打算将快速滚动作为一项重要功能,则需要将内存中的视图数量增加到5或7.您在内存中保存的视图越多,无缝滚动就越多,但您需要付出代价内存使用情况。

我不建议尝试将所有视图保留在内存中,因为设备内存将填满,您的应用程序将被终止。在任何情况下,您都可以尝试查看设备是否可以同时处理内存中的所有视图。

您可能会考虑的一个有趣选项是在加载页面时显示活动指示符。这将使滚动感觉更自然,尽管应加载视图。

看一下你的文件,我注意到的一件事是

for (int i =0; i<loopTimes; i++)
loadImagesForPage中的

您可能会尝试拆分该方法,以便它不会在一次运行中执行(同时阻止UI)。我的意思是:

for (int i =0; i<loopTimes; i++) {
    [self performSelector:@selector(loadSingleImageForPage:)
               withObject:[NSNumber numberWithInt:i]
               afterDelay:0.0];
}

其中loadSingleImageForPage:是封装for循环的当前主体的方法。通过这样做(即使用afterDelay),您加载一个页面并返回到运行循环;然后是下一个并返回运行循环;当你返回到运行循环时,你给系统一个机会来处理UI,委托调用,等等......

我希望这可以有所作为。否则,我的建议只是试图注释掉你的部分代码(例如,在仅显示占位符而不试图下载图像时检查应用程序是否正常工作等)。

编辑(2013年7月9日)

由于上面的链接似乎已经死了,这里是代码:

1 - 在您的代理上收听scrollViewDidScroll,如下所示:

-(void)scrollViewDidScroll:(UIScrollView *)myScrollView {
}

2 - 使用已知图片尺寸计算当前页面:

/**
 *  calculate the current page that is shown
 *  you can also use myScrollview.frame.size.height if your image is the exact size of your scrollview
 */
int currentPage = (myScrollView.contentOffset.y / currentImageSize.height);

3 - 查看图片是否已存在,如果没有,请添加:

// display the image and maybe +/-1 for a smoother scrolling
// but be sure to check if the image already exists, you can do this very easily using tags
if ( [myScrollView viewWithTag:(currentPage +1)] ) {
    return;
}
else {
    // view is missing, create it and set its tag to currentPage+1
}

4 - 不要忘记清理记忆:

/**
 *  using your paging numbers as tag, you can also clean the UIScrollView
 *  from no longer needed views to get your memory back
 *  remove all image views except -1 and +1 of the currently drawn page
 */
for ( int i = 0; i < currentPages; i++ ) {
    if ( (i < (currentPage-1) || i > (currentPage+1)) && [myScrollView viewWithTag:(i+1)] ) {
        [[myScrollView viewWithTag:(i+1)] removeFromSuperview];
    }
}

5 - 所有步骤的最终组合:

-(void)scrollViewDidScroll:(UIScrollView *)myScrollView {

    int currentPage = (myScrollView.contentOffset.y / currentImageSize.height);

    if ( [myScrollView viewWithTag:(currentPage +1)] ) {
        return;
    }
    else {
        // view is missing, create it and set its tag to currentPage+1
    }

    for ( int i = 0; i < currentPages; i++ ) {
        if ( (i < (currentPage-1) || i > (currentPage+1)) && [myScrollView viewWithTag:(i+1)] ) {
            [[myScrollView viewWithTag:(i+1)] removeFromSuperview];
         }
    }
}

答案 2 :(得分:0)

其他一些人,您可以在VSScroller

查看我的班级

答案 3 :(得分:0)

我写了一个简单的UIScrollView子类,就像UITableView实现单元可重用性一样,项目MMHorizontalListView在gitHub上,还有一个测试项目,所以你可以看一下如何使用它的例子,它也适用于旧的iOS版本,如4.x(可能更老......)