昨天在查某一个核心类的时候,发现有明显的内存泄漏,写法如下
private lazy var displayLink: CADisplayLink = {
let displayLink = CADisplayLink(target: self, selector: #selector(refreshUI))
displayLink.preferredFramesPerSecond = 30
displayLink.add(to: .main, forMode: .common)
displayLink.isPaused = true
return displayLink
}()
...
// 在某个地方调用懒加载
displayLink.isPaused = true
之后就没有再处理了,这明显是不对的,我先做了如下处理
// 在核心类置空之前,手动调用
displayLink.invalidate()
invalidate与NSTimer的作用是基本一样的,描述是
/* Removes the object from all runloop modes (releasing the receiver if
* it has been implicitly retained) and releases the 'target' object. */
从runloop移除,并释放target对象。从描述上看,本应就结束了,既没有在runloop中也没有持有target对象。然后实际上仍然持有target。
经过实验后发现因为displayLink是用的懒加载的block创建的,block引用了self,这引起的循环引用
因此此处我做了如下修改
private lazy var displayLink: CADisplayLink = { [unowned self] in
let displayLink = CADisplayLink(target: self, selector: #selector(refreshUI))
displayLink.preferredFramesPerSecond = 30
displayLink.add(to: .main, forMode: .common)
displayLink.isPaused = true
return displayLink
}()
捕获列表中添加unowned self,经测试,target不在被强持有。