【问题标题】:Retain cycle in Swift when Object A has Object B as a property and Object B has an array property that contains Object A?当对象 A 具有对象 B 作为属性并且对象 B 具有包含对象 A 的数组属性时,在 Swift 中保持循环?
【发布时间】:2015-06-12 00:11:42
【问题描述】:

对可能是保留周期的情况感到困惑?

我明白如果

class Object-A {
  var b: Object-B }

class Object-B {
    var a: Object-A
]

那么上面的设计很糟糕,因为如果你这样做了

var a = Object-A()
var b = Object-B()
a.b = b
b.a = a

然后这会导致两个强引用相互指向的保留循环。

但如果出现以下情况呢?

class Object-A {
    var b: Object-B 
}

class Object-B {
    var randomArrayProperty: [Object-B]
}

你试着去做

var a = Object-A()
var b = Object-B()
a.b = a
b.randomArrayProperty.append(a)

这也是一个保留周期吗?

【问题讨论】:

标签: ios swift memory-management memory-leaks retain-cycle


【解决方案1】:

一般来说,手动引用计数和自动引用计数,引用ilands都会泄漏。引用循环可以由不止 2 个对象组成。

也就是说,我鼓励您在操场上测试一些代码,因为您问题中的示例存在一些语法和语言错误。

下面的代码可能是一个起点:

class ObjectA {
    let name: String
    var b: ObjectB

    init(name: String, b: ObjectB) {
        self.name = name
        self.b = b
    }

    deinit {
        print("\(name) deallocated")
    }
}

class ObjectB {
    let name: String
    var randomArrayProperty = [ObjectA]()

    init(name: String) {
        self.name = name
    }

    deinit {
        print("\(name) deallocated")
    }
}

// Create a _possible_ leak. It depends on what we'll do next
var b: ObjectB? = ObjectB(name: "Foo B")
var a: ObjectA? = ObjectA(name: "Bar A", b: b!)
b?.randomArrayProperty.append(a!)

// No leaks
a = nil
// Remove a from array inside b, a will dealloc
b?.randomArrayProperty.removeLast()
b = nil

// Recreate a _possible_ leak.
b = ObjectB(name: "Foo1 B")
a = ObjectA(name: "Bar1 A", b: b!)
b?.randomArrayProperty.append(a!)

// Leaks
a = nil
b = nil

然后继续玩变体;-)

希望对你有帮助

【讨论】:

  • 感谢您的帮助。它对启动一个新项目并逐步调试它帮助最大,以查看这些指针发生了什么。最后,a = nil 和 b=nil 并没有导致 deinit 方法触发(因此没有打印语句),然后我尝试了 Leaks 工具并看到一个红色条出现。这绝对是内存泄漏......除非你(就像你上面所做的那样)正确地从 b 的数组属性中删除一个指针!
【解决方案2】:

我想是的,有一个保留周期。什么仪器显示内存泄漏?

【讨论】:

  • 好吧,Analyze 似乎没有做任何不寻常的事情。
  • 我尝试了 Leaks,但在 Leaks 部分也没有显示任何内容