IOS闭包循环引用(Swift)

原创Blog,转载请注明出处

http://blog.csdn.net/column/details/swift-hwc.html

一、何时回形成闭包循环引用?

当闭包捕获自身引用,并且同时销毁的时候,就会导致循环引用。

不熟悉闭包的同学参见这篇文章

Swift入门教程系列6-闭包

例如:

这里声明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()    
    }    
}

输出

闭包调用函数

这时候的内存结构如图

IOS闭包循环引用(Swift)_第1张图片

此时,instance这块内存的引用计数为2,闭包引用计数为1

然后将instance = nil则断开一条强引用,如图


此时,两块内存循环引用,引用计数都为1,内存无法释放


二、用捕获列表解决

捕获列表中的元素都是由弱引用和无助引用,对着两个概念不熟悉的同学,参照这篇文章

IOS中解决ARC类实例间循环引用(Swfit)

捕获列表的格式
在闭包前加上[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专栏

http://blog.csdn.net/column/details/swift-hwc.html

你可能感兴趣的:(ios,闭包,循环引用,swift)