斯威夫特有:
强引用
弱引用
无主参考文献
如何将无主参考与弱参考不同?
什么时候使用无主参考安全?
无主引用是否存在C / C中的dangling pointers等安全风险?
weak 和 unowned 引用都不会在引用的对象上创建 strong hold(a.k.a . 它们不会增加保留计数以防止ARC释放引用的对象) .
weak
unowned
strong
但为什么两个关键词?这种区别与 Optional 类型内置Swift语言的事实有关 . 长话短说他们:optional types提供记忆安全(这与Swift's constructor rules很好地合作 - 这是严格的,以提供这种好处) .
Optional
weak 引用允许它的可能性变为 nil (当引用的对象被释放时会自动发生),因此您的属性类型必须是可选的 - 因此作为程序员,您有义务在使用它之前检查它(基本上,编译器会尽可能地强制您编写安全代码 .
nil
unowned 引用假定它在其生命周期中永远不会成为 nil . 必须在初始化期间设置无主引用 - 这意味着引用将被定义为非可选类型,可以安全地使用而无需检查 . 如果被引用的对象以某种方式被释放,那么当使用无主参考时,应用程序将崩溃 .
来自Apple docs:
只要对于该引用有效的弱引用在其生命周期的某个时刻变为零,就使用弱引用 . 相反,当您知道在初始化期间设置引用后永远不会为nil时,请使用无主引用 .
在文档中有一些例子讨论了保留周期以及如何打破它们 . 所有这些示例都是从the docs中提取的 .
weak 关键字的示例:
class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? } class Apartment { let number: Int init(number: Int) { self.number = number } weak var tenant: Person? }
现在,对于一些ASCII艺术(你应该去see the docs - 他们有漂亮的图表):
Person ===(strong)==> Apartment Person <==(weak)===== Apartment
Person 和 Apartment 示例显示了两个属性(均允许为nil)可能导致强引用周期的情况 . 使用弱引用可以最好地解决此方案 . 两个实体都可以存在,而不必严格依赖另一个实体 .
Person
Apartment
unowned 关键字的示例:
class Customer { let name: String var card: CreditCard? init(name: String) { self.name = name } } class CreditCard { let number: UInt64 unowned let customer: Customer init(number: UInt64, customer: Customer) { self.number = number; self.customer = customer } }
在此示例中, Customer 可能有也可能没有 CreditCard ,但 CreditCard will always 与 Customer 相关联 . 为了表示这一点, Customer 类具有可选的 card 属性,但 CreditCard 类具有非可选(和无主) customer 属性 .
Customer
CreditCard
card
customer
Customer ===(strong)==> CreditCard Customer <==(unowned)== CreditCard
Customer 和 CreditCard 示例显示了一种情况,即允许一个属性为nil,另一个不能为nil的属性可能导致强引用循环 . 使用无主引用可以最好地解决此方案 .
Apple的注意事项:
弱引用必须声明为变量,以指示它们的值可以在运行时更改 . 弱引用不能声明为常量 .
还有第三种情况,两个属性应始终具有值,并且一旦初始化完成,这两个属性都不应为nil .
还有一些经典的保留周期场景,以避免在使用闭包时 .
为此,我建议您访问Apple docs,或阅读the book .
Q1. How is an “Unowned reference” different from a “Weak Reference”?
弱参考:
弱引用是一种引用,它不会强制保留它所引用的实例,因此不会阻止ARC处理引用的实例 . 因为弱引用被允许具有“无值”,所以必须将每个弱引用声明为具有可选类型 . (Apple Docs)
无主参考:
就像弱引用一样,无主引用并不会强烈保留它引用的实例 . 然而,与弱引用不同,假定无主引用始终具有值 . 因此,无主引用始终定义为非可选类型 . (Apple Docs)
何时使用每个:
只要对于该引用有效的弱引用在其生命周期的某个时刻变为零,就使用弱引用 . 相反,当您知道在初始化期间设置引用后永远不会为nil时,请使用无主引用 . (Apple Docs)
Q2. When is it safe to use an “unowned reference”?
如上所述,假定无主参考始终具有值 . 因此,只有在确定引用永远不会为零时才应使用它 . Apple Docs通过以下示例说明了无主引用的用例 .
假设我们有两个类 Customer 和 CreditCard . 客户可以在没有信用卡的情况下存在,但是没有客户就不会存在信用卡,即可以假设信用卡将始终拥有客户 . 所以,他们应该有以下关系:
class Customer { var card: CreditCard? } class CreditCard { unowned let customer: Customer }
Q3. Are “unowned reference” reference an security risk like “dangling pointers” in C/C++
我不认为所以 .
由于无主引用只是保证具有值的弱引用,因此它不应该以任何方式存在安全风险 . 但是,如果在释放引用的实例后尝试访问无主引用,则会触发运行时错误,应用程序将崩溃 .
这是我看到的唯一风险 .
Link to Apple Docs
来自Jon Hoffman的书“Mastering Swift 4.”:
弱引用和无引用引用之间的区别在于弱引用所引用的实例可以是nil,而无主引用所引用的实例不能为nil . 这意味着当我们使用弱引用时,该属性必须是可选属性,因为它可以是nil .
如果 self 在闭包中可能为零,请使用 [weak self] .
如果 self 在闭包中永远不会是nil,请使用 [unowned self] .
如果它在你使用 [unowned self] 时崩溃,那么self在该闭包的某个时刻可能是零,你可能需要使用 [weak self] .
查看闭包中使用 strong , weak 和 unowned 的示例:
https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html
摘录自link
结论要点很少
要确定您是否需要担心强,弱或无主,请问“我是否在处理参考类型” . 如果您正在使用Structs或Enums,ARC不管理这些类型的内存,您甚至不必担心为这些常量或变量指定弱或无内容 .
在父级引用子级的层次关系中,强引用很好,但反之亦然 . 实际上,强引用是大多数时候最适合的参考 .
当两个实例可选地彼此相关时,请确保其中一个实例保持对另一个实例的弱引用 .
当两个实例相关联时,其中一个实例在没有另一个实例的情况下不能存在,具有强制相关性的实例需要保持对另一个实例的无主引用 .
无主引用是一种弱引用,用于两个对象之间的Same-Lifetime关系,当一个对象只能由另一个对象拥有时 . 这是一种在对象和其中一个属性之间创建不可变绑定的方法 .
在中间swift WWDC视频中给出的示例中,一个人拥有信用卡,而信用卡只能拥有一个持有者 . 在信用卡上,此人不应该是可选的 property ,因为您不希望只有一个所有者的信用卡 . 您可以通过使信用证上的持有者属性成为弱引用来打破此循环,但这也要求您使其成为可选和变量(而不是常量) . 在这种情况下,无主参考意味着尽管CreditCard没有人的拥有权,但其生命依赖于它 .
class Person { var card: CreditCard? } class CreditCard { unowned let holder: Person init (holder: Person) { self.holder = holder } }
6 回答
weak
和unowned
引用都不会在引用的对象上创建strong
hold(a.k.a . 它们不会增加保留计数以防止ARC释放引用的对象) .但为什么两个关键词?这种区别与
Optional
类型内置Swift语言的事实有关 . 长话短说他们:optional types提供记忆安全(这与Swift's constructor rules很好地合作 - 这是严格的,以提供这种好处) .weak
引用允许它的可能性变为nil
(当引用的对象被释放时会自动发生),因此您的属性类型必须是可选的 - 因此作为程序员,您有义务在使用它之前检查它(基本上,编译器会尽可能地强制您编写安全代码 .unowned
引用假定它在其生命周期中永远不会成为nil
. 必须在初始化期间设置无主引用 - 这意味着引用将被定义为非可选类型,可以安全地使用而无需检查 . 如果被引用的对象以某种方式被释放,那么当使用无主参考时,应用程序将崩溃 .来自Apple docs:
在文档中有一些例子讨论了保留周期以及如何打破它们 . 所有这些示例都是从the docs中提取的 .
weak
关键字的示例:现在,对于一些ASCII艺术(你应该去see the docs - 他们有漂亮的图表):
Person
和Apartment
示例显示了两个属性(均允许为nil)可能导致强引用周期的情况 . 使用弱引用可以最好地解决此方案 . 两个实体都可以存在,而不必严格依赖另一个实体 .unowned
关键字的示例:在此示例中,
Customer
可能有也可能没有CreditCard
,但CreditCard
will always 与Customer
相关联 . 为了表示这一点,Customer
类具有可选的card
属性,但CreditCard
类具有非可选(和无主)customer
属性 .Customer
和CreditCard
示例显示了一种情况,即允许一个属性为nil,另一个不能为nil的属性可能导致强引用循环 . 使用无主引用可以最好地解决此方案 .Apple的注意事项:
还有第三种情况,两个属性应始终具有值,并且一旦初始化完成,这两个属性都不应为nil .
还有一些经典的保留周期场景,以避免在使用闭包时 .
为此,我建议您访问Apple docs,或阅读the book .
Q1. How is an “Unowned reference” different from a “Weak Reference”?
弱参考:
无主参考:
何时使用每个:
Q2. When is it safe to use an “unowned reference”?
如上所述,假定无主参考始终具有值 . 因此,只有在确定引用永远不会为零时才应使用它 . Apple Docs通过以下示例说明了无主引用的用例 .
假设我们有两个类
Customer
和CreditCard
. 客户可以在没有信用卡的情况下存在,但是没有客户就不会存在信用卡,即可以假设信用卡将始终拥有客户 . 所以,他们应该有以下关系:Q3. Are “unowned reference” reference an security risk like “dangling pointers” in C/C++
我不认为所以 .
由于无主引用只是保证具有值的弱引用,因此它不应该以任何方式存在安全风险 . 但是,如果在释放引用的实例后尝试访问无主引用,则会触发运行时错误,应用程序将崩溃 .
这是我看到的唯一风险 .
Link to Apple Docs
来自Jon Hoffman的书“Mastering Swift 4.”:
如果 self 在闭包中可能为零,请使用 [weak self] .
如果 self 在闭包中永远不会是nil,请使用 [unowned self] .
如果它在你使用 [unowned self] 时崩溃,那么self在该闭包的某个时刻可能是零,你可能需要使用 [weak self] .
查看闭包中使用 strong , weak 和 unowned 的示例:
https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html
摘录自link
结论要点很少
要确定您是否需要担心强,弱或无主,请问“我是否在处理参考类型” . 如果您正在使用Structs或Enums,ARC不管理这些类型的内存,您甚至不必担心为这些常量或变量指定弱或无内容 .
在父级引用子级的层次关系中,强引用很好,但反之亦然 . 实际上,强引用是大多数时候最适合的参考 .
当两个实例可选地彼此相关时,请确保其中一个实例保持对另一个实例的弱引用 .
当两个实例相关联时,其中一个实例在没有另一个实例的情况下不能存在,具有强制相关性的实例需要保持对另一个实例的无主引用 .
无主引用是一种弱引用,用于两个对象之间的Same-Lifetime关系,当一个对象只能由另一个对象拥有时 . 这是一种在对象和其中一个属性之间创建不可变绑定的方法 .
在中间swift WWDC视频中给出的示例中,一个人拥有信用卡,而信用卡只能拥有一个持有者 . 在信用卡上,此人不应该是可选的 property ,因为您不希望只有一个所有者的信用卡 . 您可以通过使信用证上的持有者属性成为弱引用来打破此循环,但这也要求您使其成为可选和变量(而不是常量) . 在这种情况下,无主参考意味着尽管CreditCard没有人的拥有权,但其生命依赖于它 .