進行状況ビューを 1.5 秒で 1000 回更新しようとしています。画面は 1 秒間に 60 回しか更新されないため、これは速すぎます。つまり、進行状況バーが実際に画面に再描画されるたびに、進行状況バーを 10 回以上更新しています。
代わりに、0.1 秒間隔で 15 回の更新を提案し、進行状況バーを毎回 1/15 ずつ変更します。
コードのパフォーマンスを確認する 1 つの方法は、CACurrentMediaTime
関数を使用してタイムスタンプを取得することです。その方法を示すサンプル コードを次に示します。progressStart
変数は、ボタン プレス イベントが発生したときのタイムスタンプであり、NSLog
開始時刻からの経過時間を出力します。
このコードの重要な機能は、スリッページを最小限に抑えるためperformSelector
に、メソッドがメソッドのできるだけ早い段階で呼び出されることです。updateProgress
@interface ViewController ()
{
CFTimeInterval progressStart;
int progressCount;
}
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@end
- (void)updateProgress
{
if ( progressCount > 0 )
[self performSelector:@selector(updateProgress) withObject:nil afterDelay:0.1];
self.progressView.progress = progressCount / 15.0;
NSLog( @"%2d %.3lf", progressCount, CACurrentMediaTime() - progressStart );
progressCount--;
}
- (IBAction)someButtonPressed
{
self.progressView.progress = 1.0;
progressStart = CACurrentMediaTime();
progressCount = 15;
[self updateProgress];
}
そして、これが典型的な実行の結果です
2015-07-01 13:05:57.610 Progress[8354:907] 15 0.000
2015-07-01 13:05:57.711 Progress[8354:907] 14 0.101
2015-07-01 13:05:57.813 Progress[8354:907] 13 0.203
2015-07-01 13:05:57.914 Progress[8354:907] 12 0.304
2015-07-01 13:05:58.015 Progress[8354:907] 11 0.405
2015-07-01 13:05:58.116 Progress[8354:907] 10 0.506
2015-07-01 13:05:58.218 Progress[8354:907] 9 0.608
2015-07-01 13:05:58.319 Progress[8354:907] 8 0.709
2015-07-01 13:05:58.420 Progress[8354:907] 7 0.810
2015-07-01 13:05:58.520 Progress[8354:907] 6 0.910
2015-07-01 13:05:58.621 Progress[8354:907] 5 1.011
2015-07-01 13:05:58.722 Progress[8354:907] 4 1.112
2015-07-01 13:05:58.823 Progress[8354:907] 3 1.213
2015-07-01 13:05:58.924 Progress[8354:907] 2 1.314
2015-07-01 13:05:59.024 Progress[8354:907] 1 1.415
2015-07-01 13:05:59.125 Progress[8354:907] 0 1.515
このperformSelector:afterDelay
メソッドには、各イベントで約 1 ミリ秒のずれがあることに注意してください。総ずれは 15 ミリ秒でした。デバイスの画面更新レートは 60 フレーム/秒、つまり 16.7 ミリ秒/フレームです。そのため、ずれの合計は 1 フレーム時間未満であり、ユーザーには気付かれません。
コメントで rmaddy が指摘したように、を使用するNSTimer
と、ほとんどのスリッページを回避できます。ただし、最後のタイマー イベントは任意の時間だけずれることがあります。