原创Blog,转载请注明出处
http://blog.csdn.net/column/details/swift-hwc.html
当闭包捕获自身引用,并且同时销毁的时候,就会导致循环引用。
不熟悉闭包的同学参见这篇文章
例如:
这里声明description为一个闭包,这个闭包为lazy变量(lazy 变量只有在需要的时候才会被初始化),这个闭包的功能就是调用类的实例函数
class CSDN{
var name:String?
lazy var description:()->() = {
self.print()
}
func print(){
println("闭包调用函数")
}
init(name:String?){
self.name = name
}
deinit{
println("内存将要释放")
}
}
class ViewController: UIViewController{
var instance:CSDN? = CSDN(name:"hello hwc")
override func viewDidLoad(){
super.viewDidLoad()
instance?.description()
instance = nil//这里本应该调用析构函数,但是因为循环引用没有调用
}
override func didReceiveMemoryWarning(){
super.didReceiveMemoryWarning()
}
}
输出
闭包调用函数
这时候的内存结构如图
此时,instance这块内存的引用计数为2,闭包引用计数为1
然后将instance = nil则断开一条强引用,如图
此时,两块内存循环引用,引用计数都为1,内存无法释放
二、用捕获列表解决
捕获列表中的元素都是由弱引用和无助引用,对着两个概念不熟悉的同学,参照这篇文章
捕获列表的格式在闭包前加上[unowned 想要捕获的变量]
例如
lazy var print{
[unowned self] in
}
这样,我们再重写这个工程
<pre name="code" class="plain">class CSDN{
var name:String?
lazy var description:()->() = {
[unowned self] in
self.print()
}
func print(){
println("闭包调用函数")
}
init(name:String?){
self.name = name
}
deinit{
println("内存将要释放")
}
}
class ViewController: UIViewController{
var instance:CSDN? = CSDN(name:"hello hwc")
override func viewDidLoad(){
super.viewDidLoad()
instance?.description()
instance = nil//这里会进行内存释放
}
override func didReceiveMemoryWarning(){
super.didReceiveMemoryWarning()
}
}
输出
闭包函数调用
内存将要释放
这时候的内存结构如图
此时,闭包和instance内存引用计数都为1
然后断开一条强引用(instance = nil)
此时,instance内存引用计数为0,闭包引用计数为1;然后instance内存释放,闭包引用计数为0,闭包内存释放
我的swift专栏