14

可能性の重複:
Grand Central Dispatch (GCD) vs. performSelector - need a better explanationdispatch_asyncまたはperformSelectorOnMainThreadを使用してメインスレッドでUI変更を実行しますか?

メインスレッド上で "もの" を実行するために、私はdispatch_asyncまたはperformSelectorOnMainThreadを使用する必要がありますか?適切な方法、正誤、またはベストプラクティスがありますか?

例:NSURLConnection sendAsynchronousRequest:urlRequestメソッドのブロック内でロジックを実行しています。私がUIAlertViewを提示するなどのメインビューには何かをしているので、私はUIAlertViewをメインスレッドに示す必要があります。これを行うには、次のコードを使用しています。

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 

    // code snipped out to keep this question short 

    if(![NSThread isMainThread]) 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Some Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
        [alertView show]; 
     }); 
    } 
}]; 

同じif(![NSThread isMainThread])の文では、カスタムメソッドをいくつか呼び出します。問題は、上記の私が使用しているdispatch_asyncメソッドを使用するか、代わりにperformSelectorOnMainThreadを使用する方が良いでしょうか?例えば、以下の完全なコードは:

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 

    // code snipped out to keep this question short 

    if(![NSThread isMainThread]) 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Some Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
        [alertView show]; 

      // call custom methods in dispatch_async? 
      [self hideLoginSpinner]; 
     }); 

     // or call them here using performSelectorOnMainThread??? 
     [self performSelectorOnMainThread:@selector(hideLoginSpinner) withObject:nil waitUntilDone:NO]; 
    } 
}]; 

FYI - 私は彼のメインスレッド上でこれらのアクションを実行しない場合UIAlertViewを提示するとき、私は数秒の遅延を見て、私は、デバッガwait_fences: failed to receive reply: 10004003に次のメッセージが表示されます。私はこれが主なスレッドのUIに変更を加える必要があることを学んだ...誰かがなぜ私がやっていることをやっているのだろうかと疑問に思っている場合...

+2

は密接に関連:[performSelectorOnMainThreadの違いは何?:メインキュー上とdispatch_asyncは、()](http://stackoverflow.com/questions/9335434/) –

+2

_writing_コードのPOVから最も明白な違いブロックをディスパッチする方が柔軟性があります。たとえば、プリミティブな引数を扱う方が簡単です。 –

答えて

14

リンクJosh Caswellによって提供された2つはほぼ同等です。最も顕著な違いは、performSelectorOnMainThreadはデフォルトの実行ループモードでのみ実行され、実行ループがトラッキングモードまたは他のモードで実行されている場合は待機することです。ただし、コードの作成と保守にはいくつかの重要な違いがあります。

  1. は、コンパイラがすべての通常のテストを実行する大きな利点があります。 performSelectorOnMainThreadでメソッドを誤って入力すると、コンパイル時ではなく実行時にエラーが発生します。
  2. dispatch_asyncは、__block修飾子を使用してメインスレッドからデータを返すほうが簡単です。
  3. dispatch_asyncは、オブジェクトにラップする必要がないため、プリミティブ引数を扱うほうがずっと簡単です。しかし、これには潜在的な落とし穴があります。あなたがいくつかのデータへのポインタを持っているならば、ブロックキャプチャがデータを完全にコピーしないことを覚えておいてください。一方、performSelectorOnMainThreadのために強制されるようにオブジェクトにデータをラップすると、(特別なオプションを設定しない限り)ディープコピーが実行されます。深いコピーがなければ、断続的なバグに陥り、デバッグに苛立つことがあります。つまり、dispatch_asyncに電話する前に、char *のようなものをNSStringにラップする必要があります。
+0

1. 'performSelectorOnMainThread'は宣言されていないセレクターの警告を表示するようになりました。 – ma11hew28

+0

Xcodeのビルド設定で、宣言されていないセレクタの警告を有効にすると、 'performSelectorOnMainThread'を含む@selectorが使用されるたびに_some_ビルド時間テストが行​​われます。これはタイプミスを助けますが、この警告の制限に注意してください。これは 'performSelectorOnMainThread'を呼び出すオブジェクトのセレクタだけでなく、一致するセレクタがまだ宣言されているかどうかをチェックします。第2に、これは、メソッドとセレクターを使用する前に宣言しなければならないコーディングスタイルの規約を強制します。 –

関連する問題