【问题标题】:Swift Combine .debounce memory leak?Swift Combine .debounce 内存泄漏?
【发布时间】: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


【解决方案1】:

首先,只要 Publisher 还活着,它就会占用内存,这很明显。

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

您需要检查的是,当您离开屏幕时,内存使用情况是否仍然存在,并且由于您没有取消 AnyCancellable

您需要始终牢记的是,当您将对象存储在“[AnyCancellable]”中时,您还需要在作业完成时取消()它们,在您的情况下,您应该实现以下内容:

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

【讨论】:

    【解决方案2】:

    使用内存图跟踪的模拟器中调试模式下的内存管理不是很真实。我在设备上使用 Instruments 进行了尝试,我看到一个 16 字节的 malloc 泄漏。在我看来,一个人不应该为小东西出汗,这是非常小的东西。如果您愿意,可以向 Apple 报告,否则请不要担心,开心就好。

    【讨论】:

    • 你是对的,它可能可以忽略不计,但仍然不对:)
    • 我真的不喜欢这种方法,我认为您应该始终努力对您正在编写/调查的系统/代码有更深入和更好的理解
    猜你喜欢
    • 2020-08-07
    • 2021-02-13
    • 2020-08-02
    • 2020-03-19
    • 1970-01-01
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    相关资源
    最近更新 更多