あなたの質問を正しく理解できれば、これに対する簡単な解決策があります。実行時間の長いルーチンの間、独自の処理の特定のポイントで、現在の runloop に 1 回 (または runloop の複数回) の反復を処理するように指示する必要があります。例えば、表示を更新したいとき。ダーティな更新領域を持つすべてのビューでは、runloop の実行時に drawRect: メソッドが呼び出されます。
現在の実行ループに 1 回の反復を処理するように指示するには (その後、元に戻ります...):
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];
これは、対応する drawRect を持つ (非効率的な) 実行時間の長いルーチンの例です - それぞれがカスタム UIView のコンテキストにあります:
- (void) longRunningRoutine:(id)sender
{
srand( time( NULL ) );
CGFloat x = 0;
CGFloat y = 0;
[_path moveToPoint: CGPointMake(0, 0)];
for ( int j = 0 ; j < 1000 ; j++ )
{
x = 0;
y = (CGFloat)(rand() % (int)self.bounds.size.height);
[_path addLineToPoint: CGPointMake( x, y)];
y = 0;
x = (CGFloat)(rand() % (int)self.bounds.size.width);
[_path addLineToPoint: CGPointMake( x, y)];
x = self.bounds.size.width;
y = (CGFloat)(rand() % (int)self.bounds.size.height);
[_path addLineToPoint: CGPointMake( x, y)];
y = self.bounds.size.height;
x = (CGFloat)(rand() % (int)self.bounds.size.width);
[_path addLineToPoint: CGPointMake( x, y)];
[self setNeedsDisplay];
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];
}
[_path removeAllPoints];
}
- (void) drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor( ctx, [UIColor blueColor].CGColor );
CGContextFillRect( ctx, rect);
CGContextSetStrokeColorWithColor( ctx, [UIColor whiteColor].CGColor );
[_path stroke];
}
そして、これはこのテクニックを示す完全に機能するサンプルです。
微調整することで、おそらくこれを調整して、UI の残りの部分 (つまり、ユーザー入力) も同様に反応するようにすることができます。
更新 (この手法を使用する場合の注意事項)
私は、この解決策 (runMode: を呼び出して drawRect: の呼び出しを強制する) が必ずしも優れたアイデアではないという、ここにいる他のユーザーからのフィードバックの多くに同意すると言いたいだけです。私はこの質問に、述べられた質問に対する事実に基づく「方法は次のとおり」であると感じて答えましたが、これを「正しい」アーキテクチャとして宣伝するつもりはありません。また、同じ効果を達成するための他の (より良い?) 方法がないかもしれないと言っているわけではありません。確かに、私が知らなかった他のアプローチがあるかもしれません。
更新 (Joe のサンプル コードとパフォーマンスに関する質問への回答)
表示されているパフォーマンスの低下は、描画コードの反復ごとにランループを実行するオーバーヘッドです。これには、レイヤーを画面にレンダリングするだけでなく、入力の収集や処理など、ランループが行う他のすべての処理が含まれます。
1 つのオプションとして、実行ループの呼び出し頻度を下げることが考えられます。
もう 1 つのオプションは、描画コードを最適化することです。現状では (これが実際のアプリなのか、単なるサンプルなのかはわかりません...) 高速化するためにできることはいくつかあります。最初に行うことは、すべての UIGraphicsGet/Save/Restore コードをループの外に移動することです。
ただし、アーキテクチャの観点からは、ここで言及した他のアプローチのいくつかを検討することを強くお勧めします。描画がバックグラウンド スレッド (アルゴリズムは変更されていない) で行われるように構成し、タイマーまたはその他のメカニズムを使用してメイン スレッドに通知し、描画が完了するまで UI を一定の頻度で更新できない理由はわかりません。議論に参加したほとんどの人は、これが「正しい」アプローチであることに同意すると思います。