在类和结构之间保持循环

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

只有propertyOfTypeYstruct 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 = xI was deinit'ed 将被打印出来,但是如果你这样做,deinit 永远不会被调用。

如果你使用闭包,也会发生同样的事情。

【讨论】:

一个类似的“技巧”是将代码放在do ... 块中,并在执行该块后检查是否调用了 deinit。这甚至适用于非可选项。【参考方案3】:

内存图显示参考周期

肯定有retain循环。

解决方法:应该unownedweak打破循环

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

【讨论】:

以上是关于在类和结构之间保持循环的主要内容,如果未能解决你的问题,请参考以下文章

train_test_split 函数是不是保持类之间的平衡

如何将数据集拆分为训练集和验证集类之间的保持比率?

在版本之间保持代码、数据库结构和数据库数据同步

TEASOFT软件中图片之间结构保持渐变过程

使用休眠保持基类和子类

阻止应用程序关闭