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: 的返回值,因此它不需要很强。如果是强的,那么它会保留观察者,使其成为全局并生存,直到强参考设置为零。

例子

#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 回答