2

ARC の __block が変数を保持していることを理解しています。これは、次のように、変数が割り当てられる前にブロック内の変数にアクセスするときに使用できます。

  __block __weak id observer = [[NSNotificationCenter defaultCenter] addObserverForName:MPMoviePlayerPlaybackDidFinishNotification object:player queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notif){
    // reference the observer here. observer also retains this block,
    // so we'd have a retain cycle unless we either nil out observer here OR
    // unless we use __weak in addition to __block. But what does the latter mean?
  }];

しかし、これを解析するのに問題があります。オブザーバーがブロックによって保持される場合__block、効果的に強いと同時に弱いとはどういう意味ですか? ここで何をしているの__weakですか?

4

1 に答える 1

6

__block変数がグローバルに似ており、現在のフレーム スタックを存続し、スコープで宣言するブロックからアクセスできることを意味します。

__weak変数はポイントされたオブジェクトを保持しないことを意味しますが、オブジェクトの割り当てが解除されると、__weakポインターは nil に設定されます。

あなたの場合、オブザーバーは addObserverForName:object:queue:usingBlock: の戻り値をキャッチするため、強くする必要はありません。が強い場合は、オブザーバーを保持してグローバルにし、強い参照が nil に設定されるまで存続します。

#import <Foundation/Foundation.h>

void (^foo()) ()
{
    NSString* str= [[NSString alloc]initWithFormat: @"Hey"];
    __block __weak NSString* x= str;
    return ^
    {
        NSLog(@"%@",x);
    };
}

int main(int argc, char** argv)
{
    @autoreleasepool
    {
        void (^block) ()= foo();
        block();
    }
    return 0;
}

この例では (null) が出力されます。何が起こったのか見てみましょう。

  • 文字列 @"Hey" の ARC 参照カウントは 1 です。
  • ブロックで使用されますが、弱いためブロックに保持されないため、カウントは 1 のままです。
  • ブロックが返されて実行されます。これは、foo 関数のスコープから抜け出し、文字列の割り当てが解除され、ポインター x が nil に設定されているためです。

したがって、次のようにすることができます。

void (^foo()) ()
{
    NSString* str= [[NSString alloc]initWithFormat: @"Hey"];
    return ^
    {
        NSLog(@"%@",str);
    };
}

問題ありません。str はデフォルトで強力なのでキャプチャされます。__block 指定子は必要ありません。

于 2013-01-05T12:33:33.523 に答える