2016-07-28 7 views
1

GCDのブロックにいたとき、私はいつも__weakの参照をselfに使っていました。誰もがそれをお勧めします。私は、GCDでself(テスト済み)を強く参照すると、保持サイクルを生成できないことを知っています。 アップルは、ブロックが実行されたときにselfnilならないことを保証するために、自己への__weak参照し、その_weekリファレンスへ__strong参照を使用することをお勧めします。iOS - GCD弱く強い自分への参照

- (IBAction)startGCD:(id)sender { 

    GCDVC* __weak weakSelf = self; 

    [self.activityIndicator startAnimating]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1 

     // VC2* __strong strongSelf = weakSelf; 

     [weakSelf.proArray addObject:@"2"]; 

     [NSThread sleepForTimeInterval:10]; 

     NSLog(@"%@",weakSelf.proArray); 

     dispatch_async(dispatch_get_main_queue(), ^{ // 2 
      [weakSelf.activityIndicator stopAnimating]; 
     }); 
    }); 

} 

試験1 Iボタンを押すとインジケータが回転している:

私は次のコードを持っています。 GCDが終了してGCDViewControllerが解放される前に、戻るボタンを押します。

テスト2 次に、自己への強い参照をコメント解除し、同じ手順を実行します。ブロックが終了するまで、GCDViewControllerは解放されません。しかしそれから解放される。

テスト今、私は2

だから私は自分がnilでないことを確認するかどうかをテストして正確な動作を持っている(__weakまたは__strongなし)自己を直接参照する場合は3 ブロックが実行されるときに、への参照__weakへの参照を使用しているのは、__strongです。ここで何かが恋しい?テスト2の結果を変更する例はありますか& 3?

+0

ブロック内で強い参照を作成して、ブロックの実行中に自己が割り付け解除されるシナリオを防止します。 – dan

+0

はい私はそれを知っています。しかし、__強いから自己への違いは何ですか?私が自己を直接呼び出すと、私は__strongと同様にカウントを保持します。両方のケースで出力が同じです – BlackM

+0

ブロック内で直接selfを参照すると、ブロックが周りにいる限り、selfが割り当て解除されません。ブロックの外側に弱い自己を作成し、その内部に強い自己内部を作成すると、ブロックが周りにいる間に自己を割り振り解除し、ブロックが実行されている間だけ自己を解放できます。 – dan

答えて

5

私はブロック内にあったときに__weak参照を常に使用していました。 GCDです。誰もがそれをお勧めします。

いいえ、私はそれを推奨しています誰も知りません。弱い参照は、保持サイクルが存在するいくつかの状況では意味をなさない。しかし、ブロックは(1つのselfポイントを含む)任意のオブジェクトに弱いか強い参照をキャプチャする必要があるかどうかと、私は自己への強い参照が(テストということを知っている特定のメモリ管理の問題のコードの設計と

に依存します)はGFCで のサイクルを保持できません。

ブロックをグローバルキューまたはメインキューのdispatch_asyncに渡すと、保持サイクルは発生しません。私は(__weakまたは__strongなし)自己を直接参照する場合

は今、私はたぶん、あなたは、この場合の違いを見ていない試験2

で 正確な動作を持っています。しかし、彼らは一般的に行動が異なります。基本的に、あなたの質問は、selfが指し示すオブジェクトへの強参照または弱参照を取り込むブロックの違いは何ですか?

現在のオブジェクト(selfが指し示すオブジェクト)が、潜在的にブロックを除く他のすべてのオブジェクトによって解放され、後で非同期的にブロックが実行されると、何が起こるのかが異なります。

  • ブロックが現在のオブジェクトへの強い参照を取得した場合、その参照はその間ずっとオブジェクトを有効に保ちます。したがって、オブジェクトはまだ生きており、メッセージを使用してメッセージを送信することができます。
  • ブロックが現在のオブジェクトへの弱い参照を取得した場合、現在のオブジェクトは、最後の強い参照解放された。したがってブロックの弱い参照はこの時点でnilであり、ブロックはそれを使って何もしません(strongSelfをチェックして、それがnilであることを確認するか、strongSelfにメッセージを送信します)。 nilは何もしません)。

したがって、1つの場合は処理が行われ、それ以外の場合は何も行われません。

ビューまたはビューコントローラのように、現在のオブジェクトがUI要素の一部である場合、ビュー階層内にある限りビュー階層内のものによって保持されるため、このビュー/ビューコントローラから抜け出て、他に何も参照していない状態にすることができます。

あなたの場合、ブロック内の操作はすべて[weakSelf.activityIndicator stopAnimating];、つまりUIの変更です。このコマンドが実行されているかどうかは関係ありません。これを含むビューはすでに表示されていますので、覚えておいてください。誰もこの活動指標を見ることはできません。あなたがそれを止めるかしないかによってどのような違いが生まれますか?しかし、これはこのケースに特有です。一般的に、ブロック内のコマンドがグローバルな状態を変更したり、ネットワークや何かを介して何かを送信したりします。そうした場合とそうでない場合に大きな違いがあります。

関連する問題