保留 class 和 struct 之间的循环

Retain cycle between class and struct

假设我有以下代码:

struct X {
    let propertyOfTypeY: Y
}

class Y {
    var propertyOfTypeX: X?
}

let y = Y()
let x = X(propertyOfTypeY: y)
y.propertyOfTypeX = x

如果它们都是类,那么就意味着一个保留周期。但是,我不清楚 类 和结构之间的区别如何应用于上面的示例。会不会造成retain cycle,还是因为用了struct是安全代码?

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

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 的额外引用)。

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

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

内存图显示引用周期

肯定有一个保留周期。

解决方法:应该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
}