0

Apple は、静的グローバルまたは __block ストレージ型を使用して外部変数を変更することをお勧めします。

dispatch_async() には、引数のないブロックが必要です。

そのブロック内から self.prop を変更する最もクリーンで安全な方法は何ですか?

アトミックセッターを使用しますか?

ブロックをブロックで包みますか?

メインスレッドにディスパッチしますか?

私のシナリオ: ブロックはネットワーク リクエストを行っています。完了したら、返されたデータの一部を解析し、いくつかの異なるオブジェクトにプロパティを設定して、フォローアップのネットワーク リクエストを作成できるようにする必要があります。ブロックは非同期で処理されていますが、ユーザー入力に応じて、最初のブロックから必要なデータを含む 2 番目のブロックがキューに送信される可能性があります。これが私がやりたいことです。

@implementation MyNetworkManager {
  dispatch_queue_t op_queue;
  NSURL *_redirectedURL;
}

void (^initPageOperation) (void) = ^(void) {
  NSURL *url;
  NSMutableURLRequest *urlRequest;
  url = [NSURL URLWithString:domain];
  urlRequest =
  [NSMutableURLRequest requestWithURL:url
                          cachePolicy:NSURLRequestUseProtocolCachePolicy
                      timeoutInterval:5];
  [urlRequest setHTTPMethod:@"GET"];

  NSData *data = nil;
  NSURLResponse *urlResponse = nil;
  NSError *err = nil;

  data = [NSURLConnection sendSynchronousRequest:urlRequest
                               returningResponse:&urlResponse
                                           error:&err];

  if (urlResponse) {
     if (![urlResponse.URL isEqual:url]) {
            //Here's where I want to set the redirectedURL.
            _redirectedURL = urlResponse.URL;
     }
   }
};
4

2 に答える 2

2

Apple の推奨事項は、変数の内容の変更に関連しています。代わりに変数によって参照されるオブジェクトを変更する場合(self.propあなたの場合)、問題はGCDの有無にかかわらず同じです-スレッドセーフになるようにプロパティ/メソッドをどのように記述しますか?

それには複数の答えがあります ( @synchronized { }dispatch_semaphore_X()NSLock、...)。スレッドの安全性を確保するための調査を行い、ニーズに合ったものを見つけてください。

于 2013-07-02T22:38:37.480 に答える
1

あなたが言った:

__blockApple は、静的グローバルまたはストレージ型を使用して外部変数を変更することをお勧めします。

そのように表現したかどうかはわかりません。より論理的な考え方は、「メソッドのローカル変数を変更する場合は、__blockその変数の宣言で修飾子を使用しますが、それ以外の場合はその修飾子は必要ありません」だと思います。つまり、__blockクラスのインスタンス変数 (またはプロパティ)、static変数、グローバル変数などには修飾子は必要ありません。

あなたは続けてこう言います:

dispatch_async() には、引数のないブロックが必要です。

確かにそうです。ただし、独自の完了ブロックを作成している場合は、パラメーターを持つように定義できます。または、独自のパラメーターを持つ独自のタイプの完了ブロックを持つ API 呼び出しを使用することもできます。例えば:

[NSURLConnection sendAsynchronousRequest:request
                                   queue:queue
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                           // here you can initiate the parse of the data,
                           // capturing the url from the response, or examining
                           // the error
                       }];

それcompletionHandlerはパラメータを取るブロックです。

そうです、単純なdispatch_async(またはNSOperationQueue同等のaddOperationWithBlock) はパラメーターを取りません。独自の完了ブロックを書き始めると、多くの場合、パラメーターを取るブロックを作成します。

self.propそのブロック内から変更する最もクリーンで安全な方法は何ですか?

技術的には、変更するだけです。ただし、トリックは、これに同時にアクセスする可能性のある複数のスレッドがある場合、ロックメカニズムの 1 つを介してそのクラスプロパティとの対話を同期するか、そのクラスプロパティとのすべての対話を実行することでそのロックコードを排除できることです。シリアル キュー(作成したシリアル キューまたはメイン キューのいずれか) を使用します。

アトミックセッターを使用しますか?

これは単純なデータ型でのみ機能します。ただし、オブジェクトを扱う場合、アトミック セッターはあまり役に立ちません。上記のような、変数との相互作用を同期するための他のメカニズムが必要です。

ブロックをブロックで包みますか?

並べ替えですが、技術的には、スレッドセーフを提供するブロックにラップすることではなく、そのブロックをシリアルキューにディスパッチすることです (そして、そのプロパティとの他のすべての相互作用が同じシリアルキューで行われるようにします)。

メインスレッドにディスパッチしますか?

特定の単純なケースでは、はい、それも仕事をすることができます. ただし、メイン スレッドに非常に時間のかかるものをディスパッチしないようにしてください。そうしないと、UI が影響を受ける (またはさらに悪化する) 可能性があります。

私は架空のシナリオを持っています。一般的に、私はブロックのベスト プラクティスを理解しようとしています。

非常に多くの異なるパターンがあり、ビジネス ニーズが正確に何であるかによって詳細が完全に異なるため、仮定の質問に答えるのは困難です。ベスト プラクティスについては、Rob Mayoff が参照している WWDC ビデオAsynchronous Design Patterns with Blocks, GCD, and XPC をご覧になることをお勧めします。WWDC 2012 Building Concurrent User Interfaces on iOSも参照できます。それらは、 Blocks and Grand Central Dispatch in PracticeMastering Grand Central Dispatchなどの WWDC 2011 ビデオなど、以前のビデオのコンセプトにも基づいています。

于 2013-07-03T08:09:27.893 に答える