关于iphone:当变量同时是ARC中的__block和__weak时,它意味着什么?

What does it mean when a variable is both __block and __weak in ARC?

我知道弧中的块保留了变量。然后,可以在分配变量之前访问块内的变量,如:

1
2
3
4
5
  __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在这里做什么?


__block意味着变量类似于全局变量,在当前帧堆栈中生存,并且可以由您将在作用域中声明的块访问。

__weak表示变量不保留指向的对象,但如果对象被释放,__weak指针将被设置为nil。

在您的示例中,observer捕获addobserverforname:object:queue:usingblock:的返回值,因此它不需要很强。如果它是强的,那么它就保留了观察者,使其成为全球性的,并一直存在,直到强引用被设置为零。

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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;
}

此示例打印(空),让我们看看发生了什么:

  • 字符串@"hey"的弧参考计数为1;
  • 它在块中使用,但由于它很弱,不能被块保留,所以它的计数仍然为1;
  • 返回并执行块,因为我们从foo函数作用域退出,字符串被释放,指针x被设置为nil。

所以你可以这样做:

1
2
3
4
5
6
7
8
void (^foo()) ()
{
    NSString* str= [[NSString alloc]initWithFormat: @"Hey"];
    return ^
    {
        NSLog(@"%@",str);
    };
}

没有问题:str在默认情况下是强的,所以它是被捕获的,您不需要uu块说明符。