【问题标题】:Retain cycle created - need confirmation已创建保留周期 - 需要确认
【发布时间】:2014-04-30 17:47:20
【问题描述】:

我一直在询问有关保留周期的问题,但他们中的大多数人都在谈论明确定义一个块并对其进行强烈引用。他们都没有谈论只是传递一个内联块。 我的理解是,仅将函数中的块作为参数传递,并不会创建强引用。但我只是想确保我没有误解。

所以问题是: 在成员函数中传递块会创建强引用吗?

    [self someFunctionWithCompletionCallback:^{
        [self completionFunctionality];
    }];

在这种情况下,self 是否对正在传递的块持有强引用?

这将决定我是否需要传入weakSelf。

谢谢

【问题讨论】:

    标签: ios memory-management


    【解决方案1】:

    这取决于someFunctionWithCompletionCallback: 的作用。例如,如果该方法将该块存储在一个强成员变量中,它将导致一个保留循环。如果该方法只是在执行过程中调用该块并且不存储它,则不会创建永久保留循环。

    注意这样的事情:

    - (void)someFunctionWithCompletionCallback:(void (^)())completionBlock {
        dispatch_async(^{ completionBlock() }); 
    }
    

    会暂时保留self(直到异步调度完成),因为dispatch_async会保留它的块,它会保留完成块,它会保留自己。

    【讨论】:

    • 感谢大家的回复.. 非常有帮助.. 我将此标记为答案,因为它指出了一个有趣的观点。我没有保留我的任何块..只是从被调用的函数中执行它。只是出于好奇,在什么情况下我应该保留一个块。在这里看到了一个答案,这也让我想到了stackoverflow.com/questions/12915250/…
    【解决方案2】:

    请记住循环的定义是 A->B->A(其中“->”表示“保留”)。在您的问题中, B 是一个块, A 是一个定义块文字的对象。 B->A 肯定是正确的,因为块保留其中引用的对象,而 B 引用 A。

    但是 A->B 呢?这取决于 A。仅传递一个对象并不会保留它(想象一下,如果是这种情况,无限保留无处不在!)。那么A如何处理B呢?如果 A 复制或保留 B,则 A->B,并且您有一个循环。如果没有,你就没有。

    【讨论】:

      【解决方案3】:

      当您在块体中调用[self completionFunctionality]; 时,它(块)保留self,因此它会创建strong 引用。当块的执行完成时,它会超出范围,因此它将从堆栈中删除,并且块会破坏对self 的强引用。这意味着 self 在块执行完成之前不能被释放。所以不是大家普遍理解的retain cycle

      【讨论】:

      • 你确定吗?如果再次调用该块怎么办?您确定在块运行一次后它会破坏引用吗?
      • @JesseRusak 我已经稍微更新了我的答案。块从堆栈中删除时会破坏引用。当块超出范围时,它正在从堆栈中删除。
      【解决方案4】:

      此代码不会创建保留周期。如果块是例如强或复制属性,它将是保留周期

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-29
        • 1970-01-01
        • 2018-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-12
        相关资源
        最近更新 更多