1

このことを考慮:

@interface SomeViewController : UIViewController {
    SomeChildObject *child;
}
@end

@implementation SomeViewController

- (void) viewDidLoad {
    ...
    child.delegate = self;
}

- (void) somethingHappened {
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]
        initWithTarget:child
        selector:@selector(doSomething)
        object:nil];
[someNsOperationQueue addOperation:operation];
[operation release];
}

- (void) callbackA:(SomeData *)someData {
[self performSelectorOnMainThread:@selector(callbackAonMainThread:)
                       withObject:someData
                    waitUntilDone:NO];
}

- (void) callbackAonMainThread:(SomeData *)someData {
    ... do something with results in main thread, e.g UI feedback
}

- (void) callbackB:(SomeData *)someData {
[self performSelectorOnMainThread:@selector(callbackBonMainThread:)
                       withObject:someData
                    waitUntilDone:NO];
}

- (void) callbackBonMainThread:(SomeData *)someData {
    ... do something with results in main thread, e.g UI feedback
}


@end

英語で:

メインスレッドでビューコントローラーを実行し、子モデルオブジェクトを使用して何かを実行します(ネットワーク経由でデータをフェッチします)。ビュー コントローラーは子のデリゲートであるため、子はデリゲートによって結果を通知できます。コストのかかる作業を実行するために、バックグラウンド スレッドで操作を起動する NSInvocationOperation を使用して child.doSomething メソッドを生成します。完了すると、子はデリゲート (ビュー コントローラー) の callbackA または callbackB を呼び出して結果を返します。これらのコールバックは、doSomething 呼び出しが実行されたのと同じバックグラウンド スレッドで呼び出されるため (私が思うに)、私は performSelectorOnMainThread を呼び出して制御をメイン スレッドに戻す必要があります。

これは問題なく動作しますが、コールバックごとに 2 つのコールバック関連のメソッドを用意するのは好きではありません。(実際にはより多くのコールバックがあるため、実際のコードはさらに肥大化しています。) 理想的には、次のようにします。

- (void) callbackA:(SomeData *)someData {
    if (not_running_on_main_thread) {
    [self performSelectorOnMainThread:@selector(callbackA:)
                       withObject:someData
                    waitUntilDone:NO];
    } else {
        // now running on main thread, work with the results.
    }
}

質問:

1) 「not_running_on_main_thread」テストを行うにはどうすればよいですか?

2) コールバックの肥大化を抑える他の方法はありますか?

編集:わかりました、投稿する前にNSThreadドキュメントを読んだことはありません:) [NSThread isMainThread]が探しているもののようです。しかし、これを再構築またはより良くする他の方法はありますか?

4

1 に答える 1

6

Just check for [NSThread isMainThread]. There's nothing more you can do if you need multiple callbacks which do different things.

Only one thing I do differently, my code looks like this:

- (void) callbackA:(SomeData *)someData {
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(callbackA:)
                       withObject:someData
                    waitUntilDone:NO];
        return;
    }

    // now running on main thread, work with the results.
}

This lets me get rid of the whole-function-long else and make the code a little clearer. And you can save on one indentation level this way ;-)

于 2010-01-17T10:34:32.610 に答える