在类和结构之间保持循环
Posted
技术标签:
【中文标题】在类和结构之间保持循环【英文标题】:Retain cycle between class and struct 【发布时间】:2017-07-26 16:57:10 【问题描述】:假设我有以下代码:
struct X
let propertyOfTypeY: Y
class Y
var propertyOfTypeX: X?
let y = Y()
let x = X(propertyOfTypeY: y)
y.propertyOfTypeX = x
如果这两个都是类,那么这将意味着一个保留循环。但是,我不清楚类和结构之间的差异如何应用于上面的示例。会导致retain循环,还是因为使用了struct而成为安全代码?
【问题讨论】:
【参考方案1】:是的,你有一个保留周期。
y.propertyOfTypeX = x
将值x
复制到y.propertyOfTypeX
,包括
属性x.propertyOfTypeY
是对y
的引用。
因此
y.propertyOfTypeX?.propertyOfTypeY === y
持有。你所拥有的与
class Y
var propertyOfTypeY: Y?
var y = Y()
y.propertyOfTypeY = y
只有propertyOfTypeY
是struct X
的一部分
(并且x
包含对y
的附加引用)。
【讨论】:
可能有用的是注意'struct X unowned let propertyOfTypeY: Y '将允许循环被打破。【参考方案2】:TL;DR 有一个保留周期,但您可以自己查看 自己!
struct X
let propertyOfTypeY: Y
class Y
var propertyOfTypeX: X?
deinit
print("I was deinit'ed")
do
let y = Y()
let x = X(propertyOfTypeY: y)
y.propertyOfTypeX = x
// y and x should be dealloc'ed here, because the "do scope" ends
注释掉y.propertyOfTypeX = x
和I was deinit'ed
将被打印出来,但是如果你这样做,deinit
永远不会被调用。
如果你使用闭包,也会发生同样的事情。
【讨论】:
一个类似的“技巧”是将代码放在do ...
块中,并在执行该块后检查是否调用了 deinit。这甚至适用于非可选项。【参考方案3】:
内存图显示参考周期
肯定有retain循环。
解决方法:应该unowned
或weak
打破循环
struct X
unowned let propertyOfTypeY: Y
class Y
var propertyOfTypeX: X?
deinit
print("Y deallocated")
do
let y = Y()
let x = X(propertyOfTypeY: y)
y.propertyOfTypeX = x
【讨论】:
以上是关于在类和结构之间保持循环的主要内容,如果未能解决你的问题,请参考以下文章