【发布时间】:2020-04-29 15:54:06
【问题描述】:
我想我发现了与 Swift Combine 的 debounce 运算符相关的内存泄漏。 要么是泄漏,要么是我做错了什么。 这是一个重现问题的简单示例:
@IBOutlet weak var currentValueLabel: UILabel!
var numberSubject = CurrentValueSubject<Int, Never>(0)
var bag = [AnyCancellable]()
override func viewDidLoad() {
super.viewDidLoad()
setupSubscription()
bag.removeAll()
}
func setupSubscription() {
numberSubject
.debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
.sink { [weak self] in self?.currentValueLabel.text = "\($0)" }
.store(in: &bag)
}
}
debounce 运算符的简单用法似乎导致malloc 泄漏(使用内存调试器检查):
更新setupSubscription() 以放弃debounce 似乎可以解决它:
func setupSubscription() {
numberPublisher
// .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
.receive(on: DispatchQueue.main)
.sink { [weak self] in self?.currentValueLabel.text = "\($0)" }
.store(in: &bag)
}
如果您使用此修改运行,并等待视图加载(也就是订阅发生,然后从数组中删除),您会注意到泄漏不再存在。 泄漏神奇地消失了。
如果我做错了什么,谁能告诉我?这对我来说似乎是一个错误。
谢谢!
【问题讨论】:
-
您如何看出这是泄漏?我只是看到有一个16字节的对象,不一定泄漏
-
好吧,既然我要从 bag 数组中删除所有订阅,它们应该被释放。除此之外,如果您尝试运行这段代码,并在视图加载后使用内存调试器进行检查,您应该会看到那个 16 字节的对象。堆栈跟踪指向接收器关闭。移除 debounce 操作符,再次运行,在 VC 加载后检查,内存图不会显示 16 个对象。此外,Xcode 在运行时问题导航器中将其标记为泄漏。
-
你的断点当前在第 30 行吗?
-
无断点。运行应用程序,等待视图加载,然后按下问题导航器。还用 Instuments 运行它,它承认这是一个泄漏。
标签: swift memory-leaks combine debounce