swift函数赋值给闭包引起的循环引用

2017-07-19  本文已影响0人  yuandiLiao

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)
}
上一篇下一篇

猜你喜欢

热点阅读