简体   繁体   English

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

[英]Confused why this doesn't cause a memory leak?

I noticed the other day my iOS app is leaking memory like a sieve (I wrote some automated tests that did long run thrashing and then I noticed the app just grows in size until it dies).前几天我注意到我的 iOS 应用程序正在像筛子一样泄漏 memory(我编写了一些自动化测试,这些测试确实长期运行颠簸,然后我注意到应用程序的大小只会增长直到它死掉)。

I had long suspected, that I was going to get more disciplined about closure variables.我一直怀疑,我会对闭包变量更加自律。 So I've spent the day trying to figure out where my app is leaking memory.所以我花了一天时间试图找出我的应用程序在哪里泄漏 memory。 The Xcode tools so far haven't been much help.到目前为止,Xcode 工具并没有太大帮助。

A while ago I had my own Ticker (a periodic timer) object:不久前,我有自己的 Ticker(定期计时器)object:

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
        }
    }
}

Then I have a UIController subclass that first has one of these as a variables:然后我有一个 UIController 子类,它首先将其中一个作为变量:

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

And later has a method that looks like this:后来有一个看起来像这样的方法:

@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()
}

The way I understand things... my controller has a hard reference to the timer.我理解事物的方式......我的 controller 对计时器有硬性参考。 The timer has a hard reference to a closure (the tick variable).计时器有一个对闭包的硬引用(tick 变量)。 And the closure has a reference to self.并且闭包引用了self。 Shouldn't that create a cycle?这不应该创造一个循环吗?

But the Debug Memory Graph doesn't show this as an issue at all.但是调试 Memory 图表根本没有将其显示为问题。 Why not?为什么不? Is it a) not really an issue or b) the tool isn't doing what I think it is?是a)不是真正的问题还是b)该工具没有按照我的想法做?

In this instance, I generally leverage Abandoned Memory to identify the underlying issue.在这种情况下,我通常利用Abandoned Memory来识别潜在问题。 Though this article is very old, it talks about how to go over it.虽然这篇文章已经很老了,但它讨论了如何通过 go 来处理它。 After doing the same interaction multiple times, check for the classes that your app creates (not the system ones) that are not getting released.多次执行相同的交互后,检查您的应用创建的类(不是系统类)是否未发布。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM