-1

数週間のデバッグの後、テーブルビューのスクロール中に散発的なラグの原因がついに見つかりました。それらは-willChangeValueForKey:-didChangeValueForKey:外部のバイナリデータ属性を必要とします。

便宜上、私のアプリはTwitterクライアントと考えることができます。したがって、主要なエンティティは、私が設定した属性Tweetを持つエンティティです。と呼ばれる対応する非永続プロパティは、その便利なアクセサとして使用されます。thumbnail_pic_dataallowsExternalBinaryDataStoragethumbnail_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

一時的な回避策として、これら2つのKVO呼び出しはコメントアウトしたままにしておきます。何か悪いことが起こるかどうかはわかりませんCore Data Programming Guide

関連するアクセスおよび変更通知メソッド(willAccessValueForKey:、didAccessValueForKey:、willChangeValueForKey:、didChangeValueForKey:、willChangeValueForKey:withSetMutation:usingObjects:、およびdidChangeValueForKey:withSetMutation:usingObjects:)を必ず呼び出す必要があります。

最も重要なことは、これら2つのKVO呼び出しによってテーブルビューのスクロールが遅くなる理由を知りたいので、より良い回避策を見つけることができれば幸いです。

4

2 に答える 2

0

Allow me to suggest a different approach, and instead of saving the data/image as the transient property, save as the transient property the name of the image. The NSData object of the image appears of no use to you, so, dont waste memory keeping it since it seems that the only thing you need the content for is to generate the image, and instead create the NSImage object with the NSData from the web, and assign it to a NSCache value with the name of the image (the transient property of your NSManagedObject object) as the key of the image's object.

于 2012-08-09T04:25:38.083 に答える
-1

最後に、私はそれを見つけました。

-willChangeValueForKey:私の場合、スクロール中に頻繁に呼び出されると、まとめてかなり時間-didChangeValueForKey:NSFetchedResultsControllerDelegateかかるメソッドが呼び出されます。これら 2 つの KVO 呼び出しを省略することで、これらの不要なNSFetchedResultsControllerDelegateメソッド呼び出しを省くことができますが、そうすべきではありません。なぜなら、Apple doc ではそうしないように明示的に指示されており、そうすると悪いことが起こることがわかっているからです。

基本的に、この問題は「NSFetchedResultsChangeUpdate でどのプロパティが変更されたかを知るにはどうすればよいですか?」と同じ解決策を求めます。

于 2012-08-27T21:55:26.760 に答える