经过数周的调试,我终于在桌面视图滚动过程中找到了零星滞后的罪魁祸首。它们是-willChangeValueForKey:
和-didChangeValueForKey:
调用外部二进制数据属性。
为方便起见,您可以将我的应用视为Twitter客户端。因此,主要实体是Tweet
,其thumbnail_pic_data
属性设置为allowsExternalBinaryDataStorage
。名为thumbnail_picture
的相应非持久性属性用作其方便的访问者。
表格视图是推文列表视图 - 时间轴,每条推文的thumbnail_picture
都显示在其相应单元格的内联中。图片是懒洋洋地下载的。下载成功后,我使用自定义设置器设置thumbnail_pic_data
,如下所示:
- (void)setThumbnail_pic_data:(NSData *)thumbnail_pic_data {
[self willChangeValueForKey:@"thumbnail_pic_data"]; // culprit
[self setPrimitiveThumbnail_pic_data:thumbnail_pic_data];
[self didChangeValueForKey:@"thumbnail_pic_data"]; // culprit
UIImage *picture;
if (thumbnail_pic_data) {
picture = [UIImage imageWithData:thumbnail_pic_data];
}
self.thumbnail_picture = picture;
}
使用上面的代码,我看到在每次下载图片后我的表格视图中滚动的零星滞后。在我评论willChangeValueForKey:
和didChangeValueForKey:
来电后,滞后消失了。所以我知道他们是罪魁祸首。
但是,我使用以下代码得到的时序结果显示,他们长时间不使用CPU直接
:CFAbsoluteTime t1 = CFAbsoluteTimeGetCurrent();
[self willChangeValueForKey:@"thumbnail_pic_data"];
CFAbsoluteTime t2 = CFAbsoluteTimeGetCurrent();
NSLog(@"willChangeValueForKey time: %f", t2 - t1);
[self setPrimitiveThumbnail_pic_data:thumbnail_pic_data];
CFAbsoluteTime t3 = CFAbsoluteTimeGetCurrent();
NSLog(@"setPrimitiveThumbnail_pic_data time: %f", t3 - t2);
[self didChangeValueForKey:@"thumbnail_pic_data"];
CFAbsoluteTime t4 = CFAbsoluteTimeGetCurrent();
NSLog(@"didChangeValueForKey time: %f", t4 - t3);
计时结果:
willChangeValueForKey时间:0.000145
setPrimitiveThumbnail_pic_data时间:0.001512
didChangeValueForKey时间:0.001810willChangeValueForKey时间:0.000138
setPrimitiveThumbnail_pic_data时间:0.001418
didChangeValueForKey时间:0.002211willChangeValueForKey时间:0.000302
setPrimitiveThumbnail_pic_data时间:0.001891
didChangeValueForKey时间:0.003349willChangeValueForKey时间:0.000162
setPrimitiveThumbnail_pic_data时间:0.001462
didChangeValueForKey时间:0.002114
作为临时解决方法,我会留下这两个KVO电话注释掉。我不确定Core Data Programming Guide
是否会发生任何不好的事情:
您必须确保调用相关的访问和更改通知方法(willAccessValueForKey:,didAccessValueForKey:,willChangeValueForKey:,didChangeValueForKey:,willChangeValueForKey:withSetMutation:usingObjects:和didChangeValueForKey:withSetMutation:usingObjects :)。
最重要的是,我想知道为什么这两个KVO调用会使表格视图滚动缓慢,以便我能找到更好的解决方法。
答案 0 :(得分:0)
请允许我建议一种不同的方法,而不是将数据/图像保存为瞬态属性,将瞬态属性另存为图像名称。图像的NSData对象看起来没用,所以,不要浪费内存保留它,因为看起来你需要内容的唯一东西是生成图像,而是用Web上的NSData创建NSImage对象,并将其分配给NSCache值,其中包含图像名称(NSManagedObject对象的瞬态属性)作为图像对象的键。
答案 1 :(得分:-1)
最后,我发现了它。
-willChangeValueForKey:
和-didChangeValueForKey:
将导致NSFetchedResultsControllerDelegate
方法被调用,如果在我的情况下滚动期间经常调用它们,则这些方法非常耗时。省略这两个KVO调用会使我不必要的NSFetchedResultsControllerDelegate
方法调用,但我不应该这样做,因为Apple doc明确地告诉我们不要这样做,而且如果我这样做,我确实会发现坏事。
基本上,此问题需要How to know which property is changed for NSFetchedResultsChangeUpdate?
的相同解决方案