iOS - GCD弱而强烈的自我参考

Bla*_*ckM 2 objective-c ios objective-c-blocks

当我在一个街区时,我总是使用__weak引用.每个人都建议这样做.我知道在GCD中对(测试)的强引用不能产生保留周期. Apple建议使用对self 的引用,然后引用该引用,以保证在执行块时不会.selfGCDself__weak__strong_weekselfnil

我有以下代码:

- (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];
        });
    });

}
Run Code Online (Sandbox Code Playgroud)

测试1 我按下按钮,指示灯旋转.我在GCD完成之前按下后退按钮并释放GCDViewController.

测试2 然后我取消注释对self的强引用,并执行相同的过程.在块完成工作之前,GCDViewController不会被释放.但随后它被释放了.

测试3 现在,如果我直接引用自己(没有__weak__strong)我有测试2的确切行为.

因此,如果我想确保在执行块时self不会为nil,那么使用对__strong引用的__weak引用是self什么意思?我在这里想念一下吗?是否会改变测试2和3的结果?

new*_*cct 6

当我在GCD的一个区块时,我总是使用__weak引用自我.每个人都建议这样做.

不,我不知道有人建议这样做.在某些存在保留周期的情况下,弱引用是有意义的.但是一个块是否应该捕获对任何对象(包括self指向一个对象)的弱或强引用取决于所讨论的代码的特定内存管理设计和

我知道在GCD中对自我(测试)的强烈引用不能产生保留周期.

将块传递到dispatch_async全局或主队列将永远不会产生保留周期.

现在,如果我直接引用自己(没有__weak或__strong),我对测试2有确切的行为.

也许你看不出这种情况有什么不同.但他们总的来说有不同的行为.基本上,您的问题是捕获对指向的对象的强引用或弱引用的块之间的区别是什么self.

不同之处在于,如果当前对象(由其指向的对象self)已被包含其强引用的每个其他对象释放,除了可能是块,并且该块之后是异步执行的.

  • 如果块捕获了对当前对象的强引用,那么该引用将在整个时间内使对象保持活动状态.所以对象仍然存在,我们可以使用它并向它发送消息等.
  • 如果块捕获了对当前对象的弱引用,则当释放最后一个强引用时,当前对象已被释放.所以块的弱引用就是nil在这一点上,并且该块不会对它做任何事情(它要么检查strongSelf并在它看到它时返回nil,否则它将发送消息,strongSelf哪些nil什么都不做) .

所以在一种情况下,事情已经完成,而在另一种情况下,没有做任何事情

如果您的案例中的当前对象是某个UI元素(如视图或视图控制器),那么只要它在视图层次结构中,它将被视图层次结构中的内容保留,因此您需要退出这个视图/视图控制器,以便没有其他任何东西强烈引用它的情况.

在您的情况下,您在块内所做的只是[weakSelf.activityIndicator stopAnimating];改变UI.无论此命令是否运行都无关紧要,因为请记住,包含此命令的视图已停止显示.没有人能看到这个活动指标.那么如果你停止它会有什么不同呢?但这是针对这种情况的.一般来说,您可以想象块内的命令会改变一些全局状态,或者通过网络或某些东西发送一些东西,如果你这样做的话,那里会有很大的不同.