swift的闭包就类似oc中的block回调,使用的过程中可能会引起循环引用,从而造成内存泄漏。
这里记录之前公司项目中一个比较另类的使用造成的循环引用。就是把一个函数直接传给闭包,造成的引用。看一下代码比较清楚
import UIKit
class SecondViewController: UIViewController {
let test = TestObject()
override func viewDidLoad() {
super.viewDidLoad()
self.test.select = self.selectButton(index:)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.test.doSomethine()
}
func selectButton(index:Int){
print(index)
}
deinit {
print("deinit")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
import UIKit
typealias selectBtnBlock = (_ index:Int)->()
class TestObject: NSObject {
var select:selectBtnBlock?
func doSomethine(){
self.select!(1)
}
deinit {
print("6666")
}
}
这里有个SecondViewController的控制器,里面持有一个TestObject的对象,而TestObject对象中有一个typealias selectBtnBlock = (_ index:Int)->()的闭包属性。然后在SecondViewController控制器中直接将一个self.selectButton(index:)的函数赋值给TestObject对象的闭包,这是引起循环引用的关键。
self.test.select = self.selectButton(index:)
这段代码运行是没有报错的,但是这样直接赋值了之后,TestObject对象就直接对SecondViewController对象进行了strong强引用。两者相互持有造成了循环引用。这时候想到的是我对self进行weak引用,然后再指向函数可不可以呢?如下,结果还是不行的,因为selectButton的方法在self的内存中,还是被TestObject强引用持有着。
weak var weakself = self
self.test.select = weakself?.selectButton(index:)
最后只能是闭包用闭包的形式实现,不能直接指向函数,解决方法如下两种
//方法1
self.test.select = { [weak self] i in
self?.selectButton(index: i)
}
//方法2
weak var weakself = self
self.test.select = {i in
weakself?.selectButton(index: i)
}