【问题标题】:Retain Cycle Even when using Weak/Strong ARC Semantics即使使用弱/强 ARC 语义也保持循环
【发布时间】:2014-09-10 16:02:27
【问题描述】:

`我承认我不是 ARC 方面的专家,但通过一些研究和一些很棒的文章(如 this),我相信我掌握了基本知识。

但是,我目前很难过。我有一个属性定义如下。

@property (nonatomic,retain) Foo *foo;

在我的init 中,我执行以下操作。

if(self = [super init]) {

    _foo = [[Foo alloc] initWithDelegate:self];

    // async the rest
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
                                             (unsigned long)NULL), ^(void) {

        __strong typeof(weakSelf) strongSelf = weakSelf;

        if (strongSelf.foo != nil) {
                        [strongSelf.foo runTests];
        }
    });
}
return self;
}

这是我的dealloc

- (void)dealloc {
     _foo = nil;
}

如果 dispatch_aync 块被注释掉,我看到我的 Foo dealloc 在 foo 设置为 nil 后立即被调用。注释块后,不会调用 foo 的 delloc

我的保留周期正确吗?知道怎么做吗?

【问题讨论】:

  • 顺便说一句,我建议在 Foo 属性的定义中使用 strong 而不是 retain。在这种情况下几乎没有实际影响,但在 ARC 代码中,您应该使用 strongweak,而不是 retainassign。此外,在 ARC 代码中,您不再需要手动 nil 实例变量,因此您可以停用 dealloc 方法。

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


【解决方案1】:

不,您不一定有保留周期(现在在 ARC 中称为“强引用周期”)。您有这样的代码,如果 foo 在定义 strongSelf 时已经存在,foo 将一直保留到分派的代码完成。

这里唯一潜在的强引用循环是您传递给foodelegate。如果delegate 被定义为strong 类的strong 属性,那么你就有了一个强引用循环。如果它被定义为weak 属性,那么您就没有强引用循环。

【讨论】:

  • 如果我没记错的话,一旦delegateweak 的属性,就不需要发布dealloc 方法,也不需要__weak self 使用调度块。
  • 无论如何都可以在 ARC 中删除 dealloc 方法。如果delegateweak,那就没有必要了。如果delegatestrong,那么您有一个强大的引用循环(坏、坏、坏),无论如何dealloc 永远不会被调用(!)。
  • 感谢您提供的所有宝贵意见,我在这里学到了很多东西。所以 Foo 的委托属性定义为(nonatomic, assign)。这个代码库也被迁移了ARC,我认为这就是我们拥有旧属性属性的原因。
  • 表示__unsafe_unretained,表示它不会保留对象,但如果对象被释放,会留下一个悬空指针。这就是为什么weak 更好,当delegate 发布时,该指针将设置为nil,从而消除了所有类型的崩溃。将 assign 替换为 weak
  • @Rob 顺便说一句,我什至追赶这个的原因是我依靠 foo 在 dealloc 中设置为 nil 来触发 Foo 的 dealloc,它设置了 @987654350 @ 为零。我看到的是foo 内部的异步操作在dealloc 之后完成。然后在完成块内我调用delegate,当然会遇到访问冲突。
猜你喜欢
  • 1970-01-01
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 2012-02-14
  • 1970-01-01
相关资源
最近更新 更多