以编程方式创建 UITableViewCell 或从 nib 加载是不是更快?

Posted

技术标签:

【中文标题】以编程方式创建 UITableViewCell 或从 nib 加载是不是更快?【英文标题】:Is it faster to create UITableViewCell programmatically or load one from a nib?以编程方式创建 UITableViewCell 或从 nib 加载是否更快? 【发布时间】:2011-12-13 05:24:08 【问题描述】:

时间分析器显示我的应用程序中最耗时的操作是从 nib 文件加载 UITableViewCells。其中最昂贵的方法是加载带有 4KB 图像的UITableViewCell

我正在使用以下代码从笔尖加载UITableViewCell

    [[NSBundle mainBundle] loadNibNamed:@"UITableViewCellPortrait" owner:self options:NULL];
    cell = portraitCell;
    self.portraitCell = nil;

有没有人比较过以编程方式创建视图或从 nib 加载 UITableViewCell 之间的区别?

编辑: 我比较了从笔尖加载UITableViewCell 并以编程方式创建视图的重复运行的时间曲线。我的测试涉及在 3-5 秒内交替使用两个 UITableViews 大约 10 次。在每次测试中,以编程方式加载 UITableViewCell 的速度要快得多,快 2 到 6 倍。

谁能证实这些结果?

编辑: 我更新了 nib 加载代码,只加载一次 nib 文件,并为后续调用使用缓存版本。

    if (self.UITableViewPortaitNib == nil) 
        self.UITableViewPortaitNib = [UINib nibWithNibName:@"UITableViewCellPortrait" bundle:[NSBundle mainBundle]];
    

    self.UITableViewPortaitNib instantiateWithOwner:self options:NULL];
    cell = portraitCell;
    self.portraitCell = nil;

我还使用自动化工具来创建更一致的运行,结果仍然表明以编程方式加载 UITableViewCells 比加载 nib 的 UITableViewCells 更快。从 nib 加载 UITableViewCells 的平均运行时间约为 90 毫秒,而以编程方式创建 UITableViewCell 的平均运行时间为 50 毫秒。

【问题讨论】:

向我们展示您的笔尖加载代码。 感谢您查看@robmayoff。我更新了问题以包括我的加载笔尖的代码。 有趣的发现 - 你能否使用故事板和原型单元再次运行实验,表格视图在后台加载所有笔尖? 我不知道 UIKit 是线程安全的。有没有其他人尝试在后台加载 nib 文件? 【参考方案1】:

尝试创建一次UINib 对象,然后在每次需要创建新单元格时发送instantiateWithOwner:options:。来自UINib Class Reference

例如,如果您的表格视图使用 nib 文件来实例化表格视图单元格,则将 nib 缓存在 UINib 对象中可以显着提高性能。

【讨论】:

哇,帮了大忙!使用您提到的技术从 NIB 加载时,平均运行时间(对于有神论者的持续时间)从大约 300 毫秒下降到 90 毫秒。以编程方式加载,平均运行时间约为 50 毫秒。【参考方案2】:

ios 5 和 WWDC 2011 视频中提到,有一种使用 UINib 的更新方法。您在viewDidLoad: 方法中注册您的笔尖,然后在tableView:cellForRowAtIndexPath: 方法中简化代码。这可能会为您加快速度(但我从未执行过任何比较时间)。

示例: 在您的viewDidLoad: 中注册笔尖并保留对它的引用:

NSString *myIdentifier = @"ReusableCustomCell";
[self.reuseCustomCell registerNib:[UINib nibWithNibName:@"ReusableCustomCell" bundle:nil] forCellReuseIdentifier:myIdentifier];

在您的tableView:cellForRowAtIndexPath: 方法中,只需询问单元格(无需检查 nil,因为它保证在 iOS5 下返回单元格)并配置单元格:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *myIdentifier = @"ReusableCustomCell";

    ReusableCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:myIdentifier];
    // Your configuration code goes here
    cell.nameLabel.text = @"some text";
    // ....

    return cell;

代码未经测试。如果这比单独使用 UINib 更快,我会很感兴趣。

【讨论】:

这与我在第二次编辑中使用 UINib 基本相同。我无法想象它会更快,但编程肯定更好。从现在开始我会这样做 - 谢谢! “self.reuseCustomCell”指的是什么? self.reuseCustomCell 是一个类似于@property (nonatomic, strong) id reuseCustomCell; 的属性【参考方案3】:

我只加载一次 nib 单元格 (cellTemplate) 并根据需要复制它,所以从某种意义上说,这种方法既是编程的,也是基于 nib 的。

复制比我预期的要复杂,因为mutableCopy 不起作用。但是,NSKeyedArchiver 往返确实:

NSData* cellData = [NSKeyedArchiver archivedDataWithRootObject:cellTemplate];
cell = [NSKeyedUnarchiver unarchiveObjectWithData:cellData];

事实上,如果您追求原始、炽热、踏板到金属的速度,即使是存档的模板也可以计算一次并缓存。

但是您不应该测量帧速率吗?在这种情况下,UIView 的复杂性也会发挥作用。

【讨论】:

明天早上我要试试keyed归档方法。您谈到了关于帧速率的一个好点。我开始分析 UITableViewCells 的最快方法的原因是因为我的方向变化动画非常慢。在这个动画中,我在两个 UITableViewControllers 之间转换,时间分析器突出显示了当我加载 UITableViewCells 时发生的最重的堆栈跟踪。您对如何加快帧速率有什么建议吗?【参考方案4】:

可以重复使用加载后的 uitableviewcell 笔尖,然后它们会离开视图。阅读以下内容:

iPhone - What are reuseIdentifiers (UITableViewCell)?

【讨论】:

桑杰说得很好。在我的 nib 加载代码上方几行,我检查了具有适当重用标识符的单元格。

以上是关于以编程方式创建 UITableViewCell 或从 nib 加载是不是更快?的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式计算 UITableViewCell 高度包含“<br>”或“\n”的文本

以编程方式在 UITableViewCell 内创建 UIScrollView - ScrollView 不滚动

UITableView 滚动后以编程方式创建的 UITableViewCell 未正确显示

如何使用自动调整其高度的 SnapKit 以编程方式创建 UITableViewCell?

自定义 uitableViewcell 内部:UILabel 背景超出文本长度(以编程方式)

使用 Swift 以编程方式自定义 UITableViewCell