通常の(OpenGL以外の)iPhoneアプリのすべてのフレームで小さなコードを実行しようとしています。目標は、フレームカウンターを用意して、アプリの低速ポイントがどこにあるかを(推測ではなく)測定して修正し、ユーザーエクスペリエンスを向上させることです。
これまでに行ったことは、すべてのモード(追跡を含む)にCADisplayLinkを登録することです。
CADisplayLink *displayLink = [[CADisplayLink displayLinkWithTarget:self selector:@selector(frame)] retain];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
実行されるコードは次のようになります(lastDrawはNSDate *であり、intをカウントします)。
- (void) frame {
NSDate *newDate = [NSDate date];
if([newDate timeIntervalSinceDate:lastDraw] >= 1) {
label.text = [NSString stringWithFormat:@"%d FPS", count];
count = 0;
[lastDraw release];
lastDraw = [newDate retain];
}
count++;
}
ここでの考え方は、過去1秒間に描画されたフレームの数に関して1秒ごとに更新を取得することです。
これは問題なく機能しているように見えますが、UIScrollViewでスクロールすると、数字は間違いなくオフになります。普通の人のようにスクロールするだけなら、フレームレートは理にかなっているようです。ただし、上下に激しくスクロールすると、表示されるレートは1または2 fpsに低下しますが、1秒に1つだけではなく、明らかに多くのフレームが描画されます。
このようにフレームメソッドを変更すると、次のようになります。
- (void) frame {
label.text = [NSString stringWithFormat:@"%f", displayLink.timestamp];
}
スクロールすると、発生するイベントが非常に少ないことが明らかになります。
UIScrollViewsとNSRunLoopCommonModesとNSDefaultRunLoopModeを扱った多くの記事をここやWebで読んだことがありますが、私の問題を説明している人は見つかりませんでした。私が見つけた最も近いものはこの質問にありました
CADisplayLinkが画面の更新のために起動できない場合(メインスレッドが前のフレームの描画などを実行しているため)、完了するのに十分な時間がないため、CADisplayLinkがスキップする可能性があることに注意してください。
しかし、公式のドキュメントではその証拠を見つけることができないようです。私が何か間違ったことをしていることを願っています...
違いがある場合は、問題のデバイスがiOS4.3.3を実行しています。