3

メインスレッドで発生する必要がある、おそらく長い一連の呼び出しを実行する必要があります (そうしないと、UIKit がボークするため)。「長い」とは、iPad 3 でそれぞれ 0.1 秒続く 10,000 回の操作を意味します。

明らかに、それらすべてを一度にループするのはおそらく最善の考えではありません。

UIKit の応答性を維持し、ウォッチドッグをスリープ状態に保つのに十分な余裕を残しながら、これらすべてをメイン スレッドで実行する方法がわかりません(つまり、実行ループを独り占めして終了することはありません)。

誰かアイデアがありますか?iOS 5 をターゲットにします。

具体的に私がやろうとしているのはUITextPosition、 s をキャッシュすることです。これは、 aがsを取得する際にキャッシュされていUITextViewない反復的なアプローチを取っているように見えるためです。実際、私のテスト ケースでは、前者は(メイン スレッドで!) 100 秒以上かかりますが、後者は実質的に瞬時です。UITextPositionpositionFromPosition:textview.beginningOfDocument offset:600011positionFromPosition:aPositionAt600000 offset:11

4

1 に答える 1

6

なぜメインスレッドでそれをしたいのですか?典型的な答えは、これらの操作をバックグラウンド スレッドで実行し、UI の更新をメイン スレッドに送り返すことです。たとえば、Grand Central Dispatchを使用できます。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // do my time consuming task and everytime it wants to update the UI, 
    // it should dispatch that back to the main queue, e.g.

    for (NSInteger i = 0; i < 10000; i++)
    {
        // do my background work

        // now update the UI
        dispatch_async(dispatch_get_main_queue(), ^{
            // update the UI accordingly
        });
    }
});

アップデート:

フォアグラウンドでこれを行う必要があるように聞こえるので、おそらく a を使用するNSTimer方が良いかもしれません。私は大物ではNSTimerありませんが、次のように見えるかもしれません。

まず、クラス インスタンス変数があることを確認します。

NSTimer *_timer;

次に、次のように初期化できます。

- (void)startTimer
{
    _timer = [NSTimer timerWithTimeInterval:0.0 target:self selector:@selector(timerCallback:) userInfo:nil repeats:YES];
    NSRunLoop *runloop = [NSRunLoop currentRunLoop];
    [runloop addTimer:_timer forMode:NSDefaultRunLoopMode];
}

これにより、timerCallback が呼び出され、呼び出しごとに 1 つの UITextPosition が処理される可能性があります。

- (void)timerCallback:(NSTimer*)theTimer
{
    BOOL moreTextPositionsToCalculate = ...;

    if (moreTextPositionsToCalculate)
    {
         // calculate the next UITextPosition
    }
    else
    {
         [self stopTimer];
    }
}

完了したら、次のようにタイマーを停止できます。

- (void)stopTimer
{
    [_timer invalidate];    
    _timer = nil;
}
于 2012-06-27T18:45:52.053 に答える