Swift Combine .debounce内存泄漏?

时间:2020-01-12 21:00:24

标签: swift memory-leaks combine debounce

我认为我发现了与Swift Combine的反跳运算符有关的内存泄漏。 这可能是泄漏,或者我做错了什么。 这是一个重现问题的简单示例:


    @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泄漏(已使用Memory Debugger检查):

Leak with debounce

更新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)
    }

如果使用此修改运行,并等待视图加载(也就是发生订阅,然后将其从数组中删除),您将注意到泄漏不再存在。 泄漏神奇地消失了。

有人可以告诉我我做错了什么吗?对我来说,这似乎是个错误。

谢谢!

2 个答案:

答案 0 :(得分:2)

用内存图跟踪的模拟器中调试模式下的内存管理不是很实际。我在设备上使用Instruments进行了尝试,发现一个16位字节的malloc泄漏。我认为一个人不应该汗流sweat背,这是非常小的东西。您可以根据需要向Apple报告,但不要担心,要开心。

答案 1 :(得分:0)

首先,发布服务器将在其存活期间占用内存,这很明显。

如果您正在调试,并且您正在初始化接收器的屏幕中,那么您将看到它的内存使用情况。

您需要检查的是何时离开屏幕,如果内存使用情况仍然继续存在,并且因为您没有取消AnyCancellable

您需要始终牢记的是,当您将对象存储在“ [AnyCancellable]”中时,还需要在作业完成时对它们进行cancel(),在这种情况下,您应该实现以下目标:

override func viewDidDisappear(_ animated: Bool) {
     super.viewDidDisappear(animated)
     for cancellable in bag { cancellable.cancel() }
}