【问题标题】:How is self passed to methods (or how to prevent strong reference cycles)self 如何传递给方法(或如何防止强引用循环)
【发布时间】:2012-12-10 13:09:28
【问题描述】:

我目前正在考虑在使用保留自身的块时如何防止强引用循环。通常的方法似乎是只使用对 self 的弱引用:

@property (strong, nonatomic) NSOperationQueue *queue;

- (void)methodA {
    __weak id *weakSelf = self;
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        [weakSelf methodB];
    }];
    [self.queue addOperation:operation];
}

但是如果methodB看起来像这样呢:

- (void)methodB {
    [self someOtherMethod];
}

这仍然会导致强引用循环吗?或者methodB会从methodA接收到对self的弱引用作为对self的引用? (也就是说,methodB对self的引用只是对methodA的弱引用的强引用吗?)

【问题讨论】:

  • 在只使用一个对象的情况下,这是一个如何引用循环?
  • 我的理解是这样的:如果block有一个对self的强引用而不是弱引用,那么self引用的对象就不能被释放,因为block会持有对它的引用。另一方面,该块无法被释放,因为它被 self 引用(通过队列)。问题是,即使块的引用很弱,具有对 self 的语法强引用的 methodB 是否会重新引入这个循环。
  • 你可能是对的,但不是freed,而是released(保留计数--)所以当块终止时,对象将被销毁,所以它会可能没问题。
  • 我猜你可以说释放而不是释放。我的意思是在保留计数达到零后从内存中删除对象。
  • @trojanfoe 让我们假设队列被挂起并且所有对对象的强引用(由 self 引用)但块内的那些被删除。

标签: objective-c objective-c-blocks cycle self strong-references


【解决方案1】:

或者methodB会从methodA接收到对self的弱引用 它对自我的引用? (也就是说,methodB 对 self 的引用只是一个 强引用到methodA的弱引用?)

方法不会“接收”强引用或弱引用。它接收一个引用。 “强”或“弱”仅适用于变量(通常是实例变量或被块捕获的变量)。

weakSelf 是块中的弱引用。因为weakSelf是一个归零弱引用(__weak),要么它指向一个有效的对象,要么它的值为nil。如果是前者,它指向一个有效对象,并在其上调用methodB。如果是后者,向nil 发送消息什么都不做,所以什么也不会发生。

你问methodB 中的self 是否是一个强引用。强引用意味着它被保留,因此如果selfmethodB 中的强引用,则意味着它在方法的开头保留self,并在最后释放它。但是,为什么方法是否保留self 之类的参数很重要?保持循环指的是 对象 强烈地相互引用。一个函数或方法将运行然后停止;根据内存管理规则,它们对局部变量所做的任何保留都必须是临时的,并且对保留周期没有影响。 (技术上的答案是否定的,self 不保留在 ARC 中,包括 self 在内的参数通常不会保留在 MRC 中。但正如我所说,这真的不相关。)

【讨论】:

  • 严格来说并非如此。在 ARC 中,self 一个强引用。然而,作为一种优化,在给定的方法调用中,ARC 只是借用它的调用者对self 的引用,而不是保留/释放它。这确实意味着您可以在使用 self 时通过导致唯一剩余的引用超出范围(不包括 self 变量)来无意中释放它,但这对于不保留的性能胜利来说是一个很小的代价/一直释放self
  • @KevinBallard:这正是我所说的非强参考。对于在 ARC 中作为强引用的函数的任何其他对象参数,不能像那样无意中释放它。
  • 理论上是强参考。它没有在self 上保持主动保留的事实仅仅是一种优化。如果 ARC 可以证明不需要其他强变量(例如,同一个对象位于两个具有相同生命周期的变量中,并且编译器知道这一点,因此只有一个真正需要保留)。
  • @KevinBallard:如果行为不同,这不是“优化”。对于其他强变量,如果 ARC 无法证明不需要它,则保留它们(因此行为与始终保留它的行为无法区分)。使用self,ARC 明确地永远不会保留它,即使它无法证明它是不需要的。因此,self 的行为与 unsafe_unretained 的行为无法区分。
  • 不,不是。微不足道的反例:self = nil 实际上释放了self 的旧值。 self 周围的行为不经常保留/释放被认为是一种优化,不幸的是它引入了在不使用时销毁 self 的可能性,但这是良好性能所必需的。
【解决方案2】:

我终于找到了part in the documentation that kind of answers this question。所以看起来 methodB 确实收到了块对 self 的弱引用。

【讨论】:

  • 不。对弱引用的任何读取都被评估为objc_loadWeak(ref),它返回一个对给定变量的自动释放引用,或者可能是objc_loadWeakRetained(ref),它返回一个强引用。无论哪种方式,该方法都是在对象本身上调用的,而不是在弱引用上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-02
相关资源
最近更新 更多