保留类和结构之间的循环

use*_*248 4 memory-leaks retain-cycle swift

假设我有以下代码:

struct X {
    let propertyOfTypeY: Y
}

class Y {
    var propertyOfTypeX: X?
}

let y = Y()
let x = X(propertyOfTypeY: y)
y.propertyOfTypeX = x
Run Code Online (Sandbox Code Playgroud)

如果这些都是类,则意味着保留周期.但是,我不清楚类和结构之间的差异如何应用于上面的示例.它会导致保留周期,还是因为结构的使用而成为安全的代码?

Mar*_*n R 7

是的,你有一个保留周期.

y.propertyOfTypeX = x
Run Code Online (Sandbox Code Playgroud)

将值复制xy.propertyOfTypeX,包括x.propertyOfTypeY作为引用的属性y.

因此

y.propertyOfTypeX?.propertyOfTypeY === y
Run Code Online (Sandbox Code Playgroud)

成立.你拥有的基本上是相同的

class Y {
    var propertyOfTypeY: Y?
}

var y = Y()
y.propertyOfTypeY = y
Run Code Online (Sandbox Code Playgroud)

只有那propertyOfTypeYstruct X (和x另外一个参考y)的一部分.


Edg*_*gar 5

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
Run Code Online (Sandbox Code Playgroud)

注释掉y.propertyOfTypeX = xI was deinit'ed打印出来,但是如果您执行该作业,deinit则永远不会调用它。

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

  • 类似的“技巧”是将代码放入`do {...}`块中,并在执行该块后检查是否调用了deinit。即使非可选选项也可以使用。 (3认同)

Was*_*sim 5

内存图显示引用周期

在此输入图像描述肯定有一个保留周期。

解决办法:应该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
}
Run Code Online (Sandbox Code Playgroud)