【问题标题】:Retain Cycle in ARCARC中的保留周期
【发布时间】:2012-09-29 22:10:27
【问题描述】:

我从未从事过非 ARC 项目。我刚刚在基于 ARC 的项目中遇到了一个僵尸。我发现是因为保留循环。我只是想知道什么是保留循环。可以

你能给我举一个保留周期的例子吗?

【问题讨论】:

  • 由于保留循环,不会出现僵尸。

标签: objective-c xcode automatic-ref-counting retain-cycle


【解决方案1】:

保留循环是对象A 保留对象B 和对象B 同时保留对象A 的情况*。这是一个例子:

@class Child;
@interface Parent : NSObject {
    Child *child; // Instance variables are implicitly __strong
}
@end
@interface Child : NSObject {
    Parent *parent;
}
@end

您可以在 ARC 中使用 __weak 变量或 weak 属性来修复“反向链接”,即指向对象层次结构中直接或间接父级的链接:

@class Child;
@interface Parent : NSObject {
    Child *child;
}
@end
@interface Child : NSObject {
    __weak Parent *parent;
}
@end


* 这是最原始的保留循环形式;可能有一长串物体在一个圆圈中相互保留。

【讨论】:

  • 保留循环会导致ARC内存泄漏吗?
  • @Raj 绝对!保留周期不是 ARC 特定的,它们会在 ARC 和非 ARC 方案中导致内存泄漏。
  • 我们可以避免它们导致内存泄漏,正如我在 cmets 中对 @Simon_Germain 的回答所解释的那样。
【解决方案2】:

什么是保留循环:当两个对象保持对彼此的引用并被保留时,它会创建一个保留循环,因为两个对象都试图相互保留,因此无法释放。

@class classB;

@interface classA

@property (nonatomic, strong) classB *b;

@end


@class classA;

@interface classB

@property (nonatomic, strong) classA *a;

@end

为避免使用 ARC 保留循环,只需使用 weak 引用声明其中一个循环,如下所示:

@property (nonatomic, weak) classA *a;

【讨论】:

  • 无法发布?如果我们小心地为破坏链的其中一个属性重新分配一些其他对象,它可能会被释放,对吗?我特地问,因为我听过很多次不可能发布。
  • cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html 的标题“避免保留循环规则 #4:使用“关闭”方法来中断循环”似乎证实了可以中断保留循环。最好避免,但如果它会造成复杂性,它仍然可以使用,但要小心在它们造成内存泄漏之前破坏它,从而避免泄漏。
  • Impossible 可能有点夸张,但我们只能说它并非微不足道。没有什么是不可能的。
  • 为什么我强调这不是不可能的,因为当很多人说不可能时,试图具体掌握这样一个循环概念的人会发现很难确定他们对它的理解,例如它发生在我身上。此外,打破循环也很简单。只需简单的重新分配就会破坏它!如果foo.bar = bar; bar.foo = foo; 创建了一个保留循环,一个简单的foo.bar = baz; 会破坏它并且不会产生泄漏。正确的?这是我的理解。
  • @trss 这是我一直在寻找的 exacswer!
【解决方案3】:

这很快,但这里是 iOS 中保留周期的交互式演示:https://github.com/nickm01/RetainCycleLoggerExample

【讨论】:

    猜你喜欢
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    相关资源
    最近更新 更多