-1

经过数周的调试,我终于找到了表格视图滚动期间零星滞后的罪魁祸首。它们是-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.001810

willChangeValueForKey 时间:0.000138
setPrimitiveThumbnail_pic_data 时间:0.001418
didChangeValueForKey 时间:0.002211

willChangeValueForKey 时间:0.000302
setPrimitiveThumbnail_pic_data 时间:0.001891
didChangeValueForKey 时间:0.003349

willChangeValueForKey 时间: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 调用会导致表格视图滚动缓慢,希望我能找到更好的解决方法。

4

2 回答 2

0

请允许我提出一种不同的方法,而不是将数据/图像保存为瞬态属性,而是将图像的名称另存为瞬态属性。图像的 NSData 对象对您来说似乎没有用,因此,不要浪费内存来保存它,因为您似乎唯一需要内容的就是生成图像,而是使用来自网络的 NSData 创建 NSImage 对象,并将其分配给一个 NSCache 值,其中图像的名称(您的 NSManagedObject 对象的瞬态属性)作为图像对象的键。

于 2012-08-09T04:25:38.083 回答
-1

最后,我找到了。

-willChangeValueForKey:并且在我的情况下,如果在滚动期间频繁调用它们,-didChangeValueForKey:则会导致NSFetchedResultsControllerDelegate调用这些方法非常耗时。省略这两个 KVO 调用可以让我省去那些不必要的NSFetchedResultsControllerDelegate方法调用,但我不应该这样做,因为 Apple 文档明确告诉我们不要这样做,而且我确实看到如果我这样做会发生不好的事情。

本质上,这个问题需要相同的解决方案如何知道 NSFetchedResultsChangeUpdate 更改了哪个属性?

于 2012-08-27T21:55:26.760 回答