【问题标题】:Should function arguments be weak?函数参数应该很弱吗?
【发布时间】:2020-06-27 13:21:20
【问题描述】:

我有以下引用弱的案例:

function hello(to persons: [Person]) {
    /// should persons be also weak below?
    helloView.didHelloPressed = { [weak self] someFlag in 
        self?.configurePersons(persons)
    }
}

在上面的代码中,我弱捕获了,我知道self 应该是弱的,因为我使用了它的函数(configurePersons)。但是persons 数组(hello 函数的参数)也应该很弱吗?我认为是的,但我没有清楚地解释它。我想如果self不是nil,那么persons也不会是nil,让它变弱也没有意义。

【问题讨论】:

    标签: swift closures automatic-ref-counting weak-references


    【解决方案1】:

    你不应该“仅仅因为我看到一个闭包”就使用弱引用。

    即使使用闭包,即使使用 self,也有很多次您不想要弱引用。

    存在弱引用以打破强引用循环。就是这样。闭包的捕获变量是一种存在的强引用。如果闭包强烈捕获变量,则不会发生任何可怕的事情。

    问题是闭包捕获foo,然后将闭包存储在foo 中。这是一个强大的参考循环,需要打破。两个引用之一必须是弱引用,所以要么你应该在foo 中弱地持有闭包,或者你应该在clsoure 中弱地捕获foo。

    您的persons 的类型为Array<Person>。如果其中一个Person 对象具有对helloView 的强引用,则可能存在一个强引用循环,而helloView 本身也对其didHelloPressed 闭包具有强引用。但这会很奇怪,而且几乎可以肯定(希望!)不是你在做什么,所以不,没有必要弱捕获persons。

    更重要的是,根据helloView 和self 在这种情况下的关系,你完全有可能也想强烈地捕捉自我。

    【讨论】:

    • self 在这种情况下是UIView 的子类。 helloView 是 self 的子视图。那么,self 是否应该被强烈捕获?为什么?
    • @neo 如果我没记错的话,UIViews 坚决保留他们的子视图。如果helloView 被self 强力持有,didHelloPressed 被helloView 强力持有,并且self 被didHelloPressed 闭包强力捕获,那么是的,你会有一个强大的引用循环。您可以通过 1) 使 helloView 被 self 弱引用(不可能,因为您不控制定义 UIView.subviews 的 UIKit 代码,另外,这是一种拥有关系,所以强烈引用是有意义的),2) 使helloView 弱引用didHelloPressed 闭包,或者...
    • ... 3) 使didHelloPressed 弱捕获self。 #3 可能是最合乎逻辑的选择。这有意义吗?
    • 啊,我明白你的意思了。是的,你可以做到,有什么让你担心你做不到的?你甚至不需要弱捕获personsView,只要没有强循环。只要personsView 没有对helloView 的强引用,你就可以了,否则你会得到这个循环:helloView -> didHelloPressed -> personsView -> helloView 。我认为您应该编写一些内存泄漏,并花一些时间在内存图调试器和工具上,以真正了解它们是什么、它们如何工作以及如何解决它们
    • "花一些时间在内存图调试器和仪器上,真正了解它们是什么,它们是如何工作的,以及如何解决它们"
    【解决方案2】:

    Array 是 Swift 中的值类型。它不是由 ARC 管理的。所以,答案是否定的。

    【讨论】:

    • 但是如果Person 是类呢?
    • 你的意思是如果数组包含引用类型,那么整个对象([Person])无论如何都被视为值类型?
    • 我的意思是 func 不会增加保留计数。尝试通过CFGetRetainCount func 检查保留计数。
    • 检查保留计数是什么?如果你的意思是persons,Xcode 不允许我这样做,因为它不能转换为 CFTypeRef
    • "它不是由 ARC 管理的。"不太好。它是一个包含对堆分配缓冲区的引用的结构,该缓冲区本身在很大程度上是由 ARC 管理的。
    【解决方案3】:

    在 Swift 中,函数参数是强引用的。我也不确定是否有办法将任何参数作为弱引用传递。在这种情况下,没有调用函数hello(to: person) 的循环。所以,答案是否定的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-04
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 1970-01-01
      • 2021-03-02
      • 2021-08-26
      相关资源
      最近更新 更多