当一个变量在ARC中同时是__block和__weak时,它意味着什么?

Aar*_*ron 1 memory iphone objective-c ios automatic-ref-counting

我知道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?
  }];
Run Code Online (Sandbox Code Playgroud)

但是我在解析这个问题时遇到了麻烦.如果__block导致观察者被块保留,那么有效地强弱都意味着什么呢?这是__weak做什么的?

Ram*_*uri 6

__block 表示变量类似于全局变量,它在当前帧堆栈中存活,并且可以在您在作用域中声明的块访问.

__weak表示变量不保留指向的对象,但如果对象被取消分配,则__weak指针将设置为nil.

在你的情况下,observer捕获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;
}
Run Code Online (Sandbox Code Playgroud)

这个例子打印(null),让我们看看发生了什么:

  • 字符串@"Hey"有1作为ARC引用计数;
  • 它在块中使用,但由于它很弱,它不会被块保留,因此它的计数仍为1;
  • 返回并执行该块,因为我们退出foo函数作用域,该字符串被释放,指针x被设置为nil.

所以你可以这样做:

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

没有问题:默认情况下str是强的,因此它被捕获,你不需要__block说明符.