【发布时间】:2016-03-28 03:33:27
【问题描述】:
我们正在尝试尽可能使用 Swift 结构。我们还使用了 RxSwift,它具有采用闭包的方法。当我们有一个结构体创建一个引用 self 的闭包时,它会创建一个strong reference cycle。
import Foundation
import RxSwift
struct DoesItLeak {
var someState: String = "initial value"
var someVariable: Variable<String> = Variable("some stuff")
let bag = DisposeBag()
mutating func someFoo() {
someVariable.subscribeNext { person in
self.someState = "something"
}
.addDisposableTo(bag)
}
}
我怎么知道这个?如果我创建 100,000 个 DoesItLeak 对象并在每个对象上调用 someFoo(),我相信我有 100,000 个具有强引用周期的对象。换句话说,当我删除包含这些对象的DoesItLeak 数组时,这些对象会保留在内存中。如果我不调用 someFoo(),就没有问题。
变量是一个类。因此,我可以通过使用 xcode 的 Instruments' Allocations 和在 Variable
中进行过滤来查看此内存问题如果我尝试使用如下所示的 [weak self],我会收到编译器错误:
someVariable.subscribeNext { [weak self] person in
编译错误是“weak cannot be applied to non-class type”
在真实/非示例代码中,我们通过 self 访问方法和变量,这是一个内存问题。
如何在保留 DoesItLeak 结构的同时解决此内存问题?
感谢您的帮助。
【问题讨论】:
-
坚持使用结构可能违反了这个在类和结构之间选择准则:“期望封装的值将被复制而不是被复制是合理的当您分配或传递该结构的实例时引用。” -- developer.apple.com/library/ios/documentation/Swift/Conceptual/…
-
我不认为你有内存泄漏——至少不是由使用 self 引用结构的闭包引起的。据我所知,当您使用 self 来引用闭包中的结构时,它只会复制该结构——它不会创建对该结构的引用。强引用循环必须只涉及类和闭包,而不涉及结构。
-
Variable类型是类还是结构? -
好的。您似乎想要一种方法来指定结构的
someVariable属性被弱捕获,但我不知道有什么方法可以做到这一点。 -
无法完成。这将如何在 C 或 C++ 中实现?我们希望
DoesItLeak是一个值类型,这意味着它可能只存在于堆栈帧上。那么我们将什么作为self传递给闭包呢?指向堆栈帧上的对象的指针,然后我们希望在闭包执行时堆栈帧仍然存在。你实际上可以在 Swift 中做到这一点,但它完全不安全。我们希望DoesItLeak成为一个值类型,但是一旦它被传递给一个引用计数对象的闭包,那么它也必须是引用计数值类型。因此,DoesItLeak不能是结构体。
标签: swift memory-leaks rx-swift