如何像 uitableviewcell 一样重用/回收自定义元素?

Posted

技术标签:

【中文标题】如何像 uitableviewcell 一样重用/回收自定义元素?【英文标题】:How to reuse/recycle custom element like uitableviewcell does? 【发布时间】:2011-06-22 07:33:06 【问题描述】:

使用 UITableView 时,我们可以使用 [[ UITableViewCell alloc] initWithStyle: reuseIdentifier:][uiTableViewInstance dequeueReusableCellWithIdentifier:] 方法重用其单元格。这有助于检查大型表格的内存,因为在给定的时刻视图中只有几个单元格。

我想创建一个有很多子视图的UIScrollView。插入所有子视图会占用我想要避免的大量内存和初始时间。 Apple API 是否提供了重用此类自定义组件(此处为 UIView 或其子类)的方法,就像使用标识符的单元格视图一样?

如果没有 API,我会创建一个,但对此有一些疑问。例如,对于每个新的子视图,我都在 previos 视图之后设置它的框架位置。回收时我应该如何更新每个子视图的框架?我应该在每个子视图被回收时删除并重新加载它的内容吗?我应该在另一个线程中进行所有这些计算以避免生涩的滚动吗?总而言之,我希望在 UITableView 中获得流畅的滚动体验,并包含所有重用内容。

这是我目前编写的代码示例:

int numberOfPages = 0;
int pageWidth = 100;
int pageHeight = 100

UIScrollView *myScrollView = //allocate and initialize a scrollview
//set its size to 100 by 100 (width equal to pageWidth)
//set paging enabled for myScrollView

通过多次调用的方法向其添加子视图

- (void) appendSubViewToScrollView 
    UIView *view = //allocate and initialize a view and dump data in it.

    CGRect rect = view.frame;
    rect.size.height = pageHeight;
    rect.size.width = pageWidth;
    rect.origin = CGPointMake(pageHeight * numberOfPages, 0);
    view.frame = rect;

    [myScrollView addSubview:view];

    numberOfPages++;

    [scrollView setContentSize:CGSizeMake(pageHeight * numberOfPages, pageWidth)];

    [view release];

编辑: 深入了解 tableview 及其单元格如何在幕后实现这一点会很有用。

【问题讨论】:

【参考方案1】:

是的,您应该每次都恢复每个子视图的内容,就像在表格视图中一样。回收子视图的优点是节省了视图存储的内存,节省了视图分配的时间,但当然内容数据管理取决于您。

因此,标准回收方法要求您使用的单元格数量等于屏幕上同时可见的视图数量 + 开始滚动时可能获得的额外单元格数量。 假设您一次显示 5 个完整视图(滚动视图稳定),然后在滚动时您将需要一个部分显示的额外视图,因此最后您需要 5+1=6 个视图。这是理论上的,建议多使用2个视图。 因此,您需要编写两个池:一个称为“visibleViews”,由作为子视图添加到滚动视图的所有视图组成,另一个称为“availableViews”,由所有可重复使用的视图组成。 然后创建所有这些视图并将它们添加到滚动视图(是的:您需要根据它们在滚动视图中的位置调整它们的框架,是的,您需要再次设置内容)。 最后,您需要通过设置委托来跟踪滚动视图的移动。此跟踪的目的是计算哪些可见视图不再可见,然后将其从可见池中移除并移至可用池。此外,代表必须了解何时会出现一个新单元格但它仍然不可见,然后从可用池中获取它(如果池为空,则分配/初始化它)并将其添加到可见池和作为子视图滚动视图。 当然,如果你想提高性能,你可以在滚动视图中放置更多子视图,以避免在单元格开始出现在屏幕上时准确地移动它们,这就是为什么我建议在滚动视图的两侧使用几个额外的视图.

WWDC 2010 上有一个很棒的视频(如果您是注册开发者,您可以访问它)关于在 iOS 中使用滚动视图:它解释了这项技术。

XCode 文档中 Apple 的 PhotoScroller 示例代码基本上实现了 WWDC 视频中所述的内容并解释了该技术。

【讨论】:

感谢 Viggio 的回复。是否有一些与此相关的代码?我可以使用一些参考。是的,我是一名注册开发人员。你能指出这个案例的相关视频吗? (“应用程序框架”?我会在闲暇时观看其余部分)。我也会下载示例代码。看起来有趣且有用。 请用复选标记将此答案标记为已接受(在向上/向下投票箭头下方。) 不幸的是,我不记得解释这种技术的视频是什么,但我记得它是通过演示解释的。有一个名为“Designing Apps with Scroll Views”的视频,但我不确定它是否是正确的视频,无论如何它都值得一看(它解释了一些漂亮的技术)。 WWDC 视频主页从这里开始:developer.apple.com/videos/wwdc/2010 使用您的开发者帐户登录,然后您将能够打开 iTunes 并下载或仅查看视频。我指的是 104(“使用滚动视图设计应用程序”)。 嗯,看XCode文档中的“PhotoScroller”代码(需要安装iOS SDK)。这是适合您的代码。 非常详细的解释。查找 PhotoScroller here。

以上是关于如何像 uitableviewcell 一样重用/回收自定义元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何像 UITableView 那样重用 UIViews?

如何使 UIPageViewController 像 tableview 重用单元一样重用控制器?

我的 UITableViewCell 正在重用以前的单元格 UIImage

UITableViewCell - 如何在重用之前重置内容

如何创建不可重用的 UITableViewCell

iOS - 如何在不同的 UITableViewCell 中重用 UIView