【问题标题】:iOS - GCD weak and strong reference to selfiOS - GCD 对 self 的弱引用和强引用
【发布时间】:2016-07-30 10:29:47
【问题描述】:

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

我有以下代码:

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

}

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

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

测试 3 现在,如果我直接引用 self(没有 __weak__strong),我与测试 2 的行为完全相同。

因此,如果我想确保在执行块时 self 不会为零,那么使用 __strong 引用 __weak 引用 self 有什么意义?我在这里想念什么吗?是否有任何示例会改变测试 2 和 3 的结果?

【问题讨论】:

  • 您在块内创建一个强引用,以防止在块运行时自我被释放的任何情况。
  • 是的,我知道。但是 __strong 到 self 与直接调用 self 有什么区别?如果我直接调用 self,我会像使用 __strong 一样增加我计数的保留。两种情况下的输出都是一样的
  • 如果您直接在块中引用 self ,那么只要块存在,它就会阻止 self 被释放。在块外部创建弱自我,然后在其内部创建强自我,允许在块周围时释放自我,并且仅在块运行时阻止它。
  • 差异在您的示例中无关紧要,因为您的块会立即执行。在某些情况下对块的引用被某些东西保留然后稍后执行,这将很重要
  • 你的意思是一个简单的块,但不是在 GCD 中?例如,当一个块被分配到一个强属性中时?

标签: ios objective-c objective-c-blocks


【解决方案1】:

当我在一个块中时,我总是使用 __weak 引用 self GCD。每个人都建议这样做。

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

我知道在 GCD 中对 self (tested) 的强引用不能产生 保留周期。

将块传递给全局或主队列上的dispatch_async 永远不会产生保留周期。

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

也许您在这种情况下看不到任何区别。但他们通常有不同的行为。基本上,您的问题是捕获对self 指向的对象的强引用或弱引用的块之间有什么区别。

不同之处在于,如果当前对象(self 指向的对象)已被所有其他持有对它的强引用的对象释放,除了可能的块,并且块随后异步执行.

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

所以在一种情况下,事情已经完成,而在另一种情况下,什么都不做。

如果你的当前对象是一些 UI 元素,比如视图或视图控制器,那么只要它在视图层次结构中,它就会被视图层次结构中的事物保留,所以你需要退出此视图/视图控制器,以便出现没有其他任何东西对其有强引用的情况。

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

【讨论】:

    猜你喜欢
    • 2013-10-01
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    相关资源
    最近更新 更多