困惑为什么这不会导致内存泄漏?

时间:2019-11-12 00:30:39

标签: ios swift memory-management memory-leaks closures

前一天,我注意到我的iOS应用正在像筛子一样泄漏内存(我编写了一些自动测试,这些测试长期运行失败,然后我发现应用的大小会不断增长,直到它死掉为止)。

我早就怀疑,我将对闭包变量有更多的纪律性。因此,我花了整整一天的时间来弄清楚我的应用程序在哪里泄漏内存。到目前为止,Xcode工具并没有太大帮助。

前一段时间,我有自己的Ticker(定期计时器)对象:

class Ticker {
    // MARK: - Properties Stored
    var interval:Duration = 1.seconds
    private var queue = DispatchQueue.main
    private var source: DispatchSourceTimer!
    var tick:()->() = {}

    // MARK: - accessing
    func start() {
        self.stop()
        self.source = DispatchSource.makeTimerSource(queue: self.queue)
        let nsgap = DispatchTimeInterval.microseconds(Int(self.interval.microseconds.rounded().magnitude))
        self.source.schedule(deadline: DispatchTime.now() + nsgap, repeating: nsgap, leeway: DispatchTimeInterval.seconds(0))
        self.source.setEventHandler(handler: self.tick)
        self.source.resume()
    }

    func stop() {
        if self.source != nil {
            self.source.cancel()
            self.source = nil
        }
    }
}

然后我有一个UIController子类,该子类首先将以下其中一个作为变量:

class MyController: UIViewController {
    var scanTimer:Ticker = Ticker()
    ...

后来有一个看起来像这样的方法:

@IBAction func startScanning() {
    self.stopScanning()
    ...
    self.scanTimer = Ticker()
    self.scanTimer.interval = 500.milliseconds
    var tickCount = 0
    self.scanTimer.tick = {
        tickCount += 1
        if tickCount > 20 {
             self.stopScanning()
        }
        if self.bleBecameActive {
            self.bleBecameActive = false
            self.startBLEScan()
        }
    }
    self.scanTimer.start()
}

我了解事物的方式...我的控制器对计时器有严格的参考。计时器对闭包(tick变量)有严格的引用。并且闭包引用了自我。那不应该创造一个周期吗?

但是Debug Memory Graph根本没有显示这是一个问题。为什么不?是(a)并不是真正的问题,还是(b)该工具没有按照我的想法去做?

1 个答案:

答案 0 :(得分:0)

在这种情况下,我通常利用Abandoned Memory来识别潜在的问题。尽管这个article很老,但它讨论了如何解决它。多次执行相同的交互后,请检查您的应用创建的尚未发布的类(而不是系统的类)。