当我们不应该既不使用[弱自我]也不使用[无主自我]?

时间:2017-08-09 16:36:42

标签: swift automatic-ref-counting

我已经阅读了有关何时应该在闭包中使用[weak self] [unowned self]的StackOverflow的几个讨论。

但是,有什么情况我们不必使用 ,因为当我们在内部明确使用self时Swift没有显示任何错误或警告关闭。

例如,我们应该在这里使用weak还是unowned

UIView.animate(withDuration: 0.3) {
    self.view.alpha = 0.0
}

2 个答案:

答案 0 :(得分:6)

如果你的闭合可能导致强参考周期,你需要使用[弱自我]或[无主自我]。

如果您将> 的属性分配并且您引用自我自我属性,则会发生这种情况 内部关闭本身。闭包是引用类型,因此基本上相同的规则适用于强引用,就像使用普通类一样。

至于您的示例,不需要[weak self][unowned self],因为您没有将闭包分配给self引用的类中的变量,因此不会成为一个强大的参考周期。

有关更多信息,请查看Swift编程语言指南的Strong Reference Cycles for Closures部分。以下是上述链接中的一个示例:当闭包引起强引用循环时:

class HTMLElement {

    let name: String
    let text: String?

    lazy var asHTML: () -> String = {
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) is being deinitialized")
    }

}

[unowned self]的闭包中没有asHTML,分配给asHTML的闭包将导致强引用周期。将asHTML的实现更改为以下内容可解决此问题:

lazy var asHTML: () -> String = {
    [unowned self] in
    if let text = self.text {
        return "<\(self.name)>\(text)</\(self.name)>"
    } else {
        return "<\(self.name) />"
    }
}

答案 1 :(得分:2)

这有点基于意见,所以我会发表意见:)。

我通常以同步性为基础。如果闭包是Async,则调用close时调用实例可能不再存在,因此应使用[weak self]。如果闭包是同步的,那么它是不必要的,并且捕获一个强引用就可以了。

这个可以扩展为包含闭包,你可以合理地期望你的实例在被调用时保持有效(例如你的View动画案例),但要注意这是一个假设关闭和你的使用将保持不变,所以它理论上可以在未来的某个时候打破。这种安全性降低,使未来的维护更加困难/危险。

对于像UIView.animate这样已建立且可预测的API,我个人倾向于为了简洁而使用强大的自我,但这是一个你自己需要做的评估,它取决于关于用法。

同样如评论中所述,功能关闭也是如此。将闭包分配给另一个变量的属性有一组不同的问题。

顺便说一下,我采用了弱引用闭包的方法,简单地在我的Type中调用另一个方法,例如。

thing.doSomethingWithAClosure() { [weak self]
    self?.doSomething()
}

它简化了逻辑,同时还强制执行更多功能/模块化代码。