数週間のデバッグの後、テーブルビューのスクロール中に散発的なラグの原因がついに見つかりました。それらは-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
一時的な回避策として、これら2つのKVO呼び出しはコメントアウトしたままにしておきます。何か悪いことが起こるかどうかはわかりませんCore Data Programming Guide
。
関連するアクセスおよび変更通知メソッド(willAccessValueForKey:、didAccessValueForKey:、willChangeValueForKey:、didChangeValueForKey:、willChangeValueForKey:withSetMutation:usingObjects:、およびdidChangeValueForKey:withSetMutation:usingObjects:)を必ず呼び出す必要があります。
最も重要なことは、これら2つのKVO呼び出しによってテーブルビューのスクロールが遅くなる理由を知りたいので、より良い回避策を見つけることができれば幸いです。