为什么使用UISegmentedControl对象的自定义表格视图单元滚动性能差?

14

我有一个带有自定义单元格的UITableView,这些单元格在xib文件中定义,在我的设备上当单元格上有UISegmentedControl时,滚动性能很差(不流畅)。NSLog语句显示单元格被分配和重用。下面是我cellForRowAtIndexPath方法的代码。根据苹果文档在xib中建立了连接。(在模拟器中平稳滚动)

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

    static NSString *MyIdentifier = @"MyIdentifier";

    UITableViewCell *cell =  
           [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil) 
    {
        [[NSBundle mainBundle] loadNibNamed:@"TableViewCell" 
                               owner:self  
                               options:nil];  
        cell = self.tvCell;
        self.tvCell = nil;
    }

    cell.layer.shouldRasterize = YES;     // build error is here

    UILabel *lbl = (UILabel *)[cell viewWithTag:1];

    [lbl setText:[NSString stringWithFormat:@"Q%i", indexPath.row+1]];  

    return cell;
}
2个回答

49

当表格单元格被滚动时,任何绘制都会导致性能问题。当你有很多子视图时,通常会有很多绘制操作进行,这将使得你的滚动变得非常卡顿,就像你所观察到的那样。有几种方法可以尝试减少这种情况。

第一步是确保你的单元格本身以及它们的尽可能多的子视图的opaque属性都设置为YES。不透明视图不需要与其下面的内容混合,这样可以节省很多时间。

你也可以将单元格的图层设置为自我栅格化,如下所示:

cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

这将会把你的视图层级结构折叠成一个扁平化的位图,而这正是核心动画喜欢绘制的类型。请注意,任何正在进行动画的视图——例如活动指示器——都会在它们改变时强制更新该位图,也就是说,非常频繁。在这种情况下,你不会想要将所有内容都光栅化;你可以只使用一个子视图来包含所有相对静态的视图(例如标签),然后在另一个子视图中添加任何这样的动态内容,并仅将第一个光栅化。


Noah,我按照你建议添加了第一行代码,然后还添加了QuartzCore框架以便我可以引用层。但是我遇到了一个构建错误:“请求在非结构体或联合体中使用成员“shouldRasterize”。你能否详细说明一下让这两行代码工作所需的步骤? - Alyoshak
3
如果您的.m文件中没有#import <QuartzCore/QuartzCore.h>,可能会出现该错误;此外,shouldRasterize仅适用于iOS 3.2及更高版本。 - Noah Witherspoon
我的.m文件中已经导入了“Yes”,还有<QuartzCore/CALayer.h>。但是,我没有使用3.2版本(正在使用3.1.3版本),这可能是问题所在。是的,而且我甚至无法成功构建针对使用iOS 3.2的此设备(iPod Touch)的应用程序。出现了代码签名错误和另一个关于iOS 3.2的奇怪错误。两者都在这里: [BEROR]CodeSign error: code signing is required for product type 'Application' in SDK 'Device - iPhone OS 3.2' [BWARN]warning: building with 'Targeted Device Family' set to iPhone only ('1') not supported with SDK 'Device - iPhone OS 3.2'. - Alyoshak
1
那么,有没有办法在不升级到3.2的情况下消除滚动的不流畅?3.2只是针对iPad的,对吧?当我在模拟器模式下使用它时,会出现一个iPad版本的模拟器。我需要解决iPodTouch设备上的滚动问题。 - Alyoshak
今天提交到App Store的任何应用程序都需要使用4.0 SDK构建。如果将目标的“部署目标”设置为3.1.x,则仍然可以在旧设备上运行,同时允许您使用新SDK的功能,例如此功能;在这种情况下,您需要在运行时(使用-respondsToSelector:)检查CALayer是否实现了setShouldRasterize方法。 - Noah Witherspoon
显示剩余5条评论

3
请确保xib中的标识符为"MyIdentifier"。如果不是,性能会受到影响。我猜“分配和重用应该是正确的”意味着在启动时分配了一些内存,之后不再分配。如果是这样,那么你可能已经做好了准备。
提高性能的另一种方法是使用代码构建表视图。它比使用xib更快。当我构建表视图时,通常是在IB中构建它们,然后将框架值复制到代码中并在代码中构建。
留出一些时间观看WWDC 2010性能视频。有很多很棒的信息,每次观看都会学到新东西。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接