[英]Why would I ever use unowned self?
iOS应用程序中出现以下模式:
class MyViewController: UIViewController {
let myModel = MyModel()
override func viewDidLoad() {
super.viewDidLoad()
myModel.foo() { [***] in
// use self here
}
}
}
class MyModel {
public func foo(complete: () -> Void) {
// do something
complete()
}
}
共识是使用[unowned self]
或[weak self]
代替[***]
,当你可以保证在完成时自我不会为零而在你不确定参考仍然有效。
我不明白为什么我会冒险使用无主,也许我确信现在参考永远不会是零,但这可能在未来发生变化。 我也可能忽略了一个边缘案例,错误发生了。 我可以很容易地总是使用弱,并在封闭的顶部放一个警卫,以便能够使用自己没有! 要么 ?。
无主的用途是什么? 它比弱+守卫更快吗? 是语法糖吗? 这似乎违背了Swift的保护开发人员免受可能导致崩溃的常见错误的理念。
unowned
与weak
相比具有边际性能优势,因为当对象消失时,运行时不必跟踪引用以将其转换为nil
。
关于保留周期(好的,强参考周期),既不weak
也不unowned
创建一个强引用(在ARC之前的术语中,既不增加保留计数)所以没有参考周期的危险,事实上,这就是为什么你需要在闭包中指定self
weak
或unowned
。
此外,对于unowned
您可以将引用用作非可选项,因此您不必在闭包中放置任何代码来解包它。
除非有一个非常好的表现理由,否则我总是使用weak
。
在你的代码中注意,我认为这两个都没有必要,因为闭包没有转义,即函数调用foo
中对它的引用在foo
的作用域结束后不会持久存在。
我认为使用unowned
增加了风险,而不是使用弱自我。 错误确实发生,它的一个例子是在视图控制器中启动API调用,让它等待响应到达并突然弹出视图控制器可能导致它被解除分配(如果没有强引用它)。 当响应到来时,我们的视图控制器对象将消失,我们的应用程序将崩溃在我们的脸上。 由我们决定在哪个地方使用哪一个。
正如杰里米指出的那样, unowned
并没有责任跟踪引用计数,因此它在强弱方面具有如此微小的性能优势。
一个无主参考应该总是有一个值。 因此,ARC永远不会将无主引用的值设置为nil,这意味着使用非可选类型定义无主引用。
简而言之, weak
是unowned
,其中unowned
者。
在导航控制器中使用无主参考的简单示例:
class RegisterViewController: UIViewController {
lazy var navigatinRightBarItemsCount: Int = { [unowned self] in
guard let navigationController = self.navigationController else { return 0 }
guard let topItem = navigationController.navigationBar.topItem else { return 0 }
guard let rightBarButtonItems = topItem.rightBarButtonItems else { return 0 }
return rightBarButtonItems.count
}()
override func viewWillAppear(_ animated: Bool) {
print("Navigation bar right side items count: ", navigationRightBarItemsCount)
}
}
这意味着RegisterViewController必须初始化,而不是我们可以安全地获得自我。 navigationController并从这里获取项目数。 如果你试图把它变成[弱自我],XCode会抱怨因为self(viewcontroller)可以是nil,所以我们必须使用unowned。
UIBarButtonItem的另一个例子
lazy final private var filterNavigationBarItem: UIBarButtonItem = { [unowned self] in
return UIBarButtonItem(image: #imageLiteral(resourceName: "filter_icon"),
style: .plain,
target: self,
action: #selector(segueToFilterJobs))
}()
我们在这看到什么? 请参阅目标,该目标代表“ 接收操作消息的对象。 ”这意味着接收操作消息的对象不能为零并且必须初始化。
您真正想要使用[无主自我]或[弱自我]的唯一时间是您创建一个强大的参考周期。 一个强大的参考周期是当存在一个所有权循环,其中对象最终彼此拥有(可能通过第三方),因此它们将永远不会被释放,因为它们都确保彼此坚持。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.