Iphone UITableViewCell自动布局性能不佳
我有点被这件事缠住了…非常感谢您的帮助。我已经花了很多时间调试这个 我得到了Iphone UITableViewCell自动布局性能不佳,iphone,ios,performance,uitableview,autolayout,Iphone,Ios,Performance,Uitableview,Autolayout,我有点被这件事缠住了…非常感谢您的帮助。我已经花了很多时间调试这个 我得到了UITableView,数据源由NSFetchedResultsController提供。在单独的视图控制器中,我使用[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:][/code>将新记录插入CoreData,保存托管对象上下文并关闭该控制器。非常标准的东西 然后,NSFetchedResultsController
UITableView
,数据源由NSFetchedResultsController
提供。在单独的视图控制器中,我使用[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:][/code>将新记录插入CoreData,保存托管对象上下文并关闭该控制器。非常标准的东西
然后,NSFetchedResultsController
接收托管对象上下文中的更改:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
break;
case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
break;
}
}
这就是问题的症结所在——这需要花费太长的时间(在iPhone4上大约3-4秒)。这似乎是花在计算单元布局上的时间
我已经从单元格中剥离了所有内容(包括自定义子类),只保留了UILabel
,但没有任何更改。然后我将单元格的样式更改为基本(或除自定义以外的任何样式),问题消失了—新单元格会立即添加
我进行了双重检查,NSFetchedResultsControllerDelegate
回调只调用一次。如果我忽略它们并执行[UITableView reloadSections:withRowAnimation:
,则不会发生任何变化-速度仍然非常慢
在我看来,默认单元格样式禁用了自动布局,这使得它们非常快。但是如果是这样的话,为什么在我按下UITableViewController
时所有东西都会快速加载
以下是该问题的呼叫跟踪:
所以问题是,这里发生了什么?为什么单元格的渲染速度如此之慢
更新1
我已经建立了一个非常简单的演示应用程序,说明了我的问题。这是消息来源-
尝试添加至少一屏单元格来感受性能问题
另外请注意,直接添加行(“立即插入!”按钮)不会导致任何速度减慢。自动布局确实会对性能造成影响。然而,在大多数情况下,这并不是很明显。有一些边缘情况下,复杂的布局,摆脱它将有意义的区别,但这不是真正的问题在这里
我没有一个很好的解释为什么应用程序会这样运行,但至少我有一个解决方案:如果表视图不在屏幕上,就不要更新表视图。这导致了这种奇怪的行为
为此,您可以检查self.tableview.window!=在获取结果控制器的委托方法中为nil
。然后,您只需将[self.tableview reloadData]
添加到视图中,视图就会出现
,以便表视图在出现在屏幕之前更新其数据
希望有帮助。如果有人对这种奇怪的行为有很好的解释,请告诉我:)好的,我终于在不牺牲动画的情况下解决了这个问题。我的解决方案是在禁用自动布局的单独Nib文件中实现UITableViewCell
的接口。加载时间稍长,您需要自己定位子视图
以下是使之成为可能的代码:
- (void)viewDidLoad {
[super viewDidLoad];
...
UINib *rowCellNib = [UINib nibWithNibName:@"RowCell" bundle:nil];
[self.tableView registerNib:rowCellNib forCellReuseIdentifier:@"ROW_CELL"];
}
当然,您需要一个包含单元格视图的RowCell.nib文件
虽然原始问题没有解决方案(对我来说,这显然是一个bug),但我正在使用此解决方案。如果您仍然希望在表视图单元格中使用自动布局,有一些方法可以使其性能更好。这是一个多步骤的过程,但一旦您这样做,您可以让自动布局引擎确定单元格的垂直大小以及单元格中其他所有内容的布局
您可以在这里找到更多详细信息:其中包括一些在iOS 8上可以使用的快捷方式。在uitableviewcell子类中使用复杂的自动布局时,我遇到了类似的问题。我的单元布局取决于来自服务器的数据,但单元状态的数量限制为六个。因此,每次我从dequeueReusableCellWithIdentifier(创建了一个新的单元格)收到nil时,我都会为刚刚创建的单元格(self.dynamicReusableIdentifier)设置一个动态/自定义reuseIdentifier。reuseIdentifier getter在UITableViewCell子类(ACellSubclass)中被重写:
self.dynamicReusableIdentifier字符串的生成基于单元格类(ACellSubclass)中定义的静态方法(configureDynamicReuseIdentifier)tableView:cellforrowatinexpath然后选择从
cell=[tableView dequeueReusableCellWithIdentifier:[ACellSubclass ConfigureDynamicResourceIdentifier:someData]]
并且重复使用的单元格的静态子视图(标签、图像)在没有任何自动布局更改的情况下进行更新。I在iOS 7的[table reloadData]中具有相同的性能。
在我的例子中,我解决了这个问题,将单元格配置代码从[cell layoutifneed]
替换为以下代码:
[cell setNeedsUpdateConstraints];
[cell setNeedsLayout];
然后把手机还给我。一切似乎都好。我希望这可以帮助其他人解决同样的问题。只是确认一下-您正在为自定义单元格分配唯一标识符并将其排队,而不是重新创建,对吗?在单元格上指定了哪些自动布局规则?是的,我正在分配唯一标识符并使用[UITableView dequeueReusableCellWithIdentifier:forIndexPath:]
。至于布局规则,我尝试了不同的规则-固定的宽度/高度和居中UILabel,以及固定的顶部/左侧边距,结果都是一样的。我遇到了完全相同的性能问题。我仍在研究这个问题,但同时我刚刚放弃了原型单元格,而是使用了自定义子类。Prog在initWithStyle
中以语法方式设置我的单元格标签和图像的框架可以避免自动布局性能问题,但当然,您也会失去自动布局带来的所有优点
[cell setNeedsUpdateConstraints];
[cell setNeedsLayout];