一个比较隐蔽的内存泄漏
出错代码
let btn: UIButton = UIButton()
btn.addAction {
btn.isSelected = !btn.isSelected
...
}
退出这个页面的时候MLeaksFinder
总是弹出弹窗说这个对象内存泄漏了,稍微研究了一下,发现btn
和UIControl
互相持有了,造成循环引用。
addAction
是一个扩展方法
class ClosureSleeve {
let closure: () -> ()
init(attachTo: AnyObject, closure: @escaping () -> ()) {
self.closure = closure
objc_setAssociatedObject(attachTo, "[\(arc4random())]", self, .OBJC_ASSOCIATION_RETAIN)
}
@objc func invoke() {
closure()
}
}
extension UIControl {
func addAction(for controlEvents: UIControl.Event = .primaryActionTriggered, action: @escaping () -> ()) {
let sleeve = ClosureSleeve(attachTo: self, closure: action)
addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
}
}
解决方案
let btn: UIButton = UIButton()
btn.addAction { [unowned btn] in
btn.isSelected = !btn.isSelected
...
}