ARC之解决闭包引起的循环强引用

copy自:swift2.0官方教程中文版---极客学院版

1.产生闭包之间的循环强引用

直接代码和上图:

class HTMLElement {
	let name: String
	let text: String?
	lazy var asHTML: Void -> String = {
		if let text = self.text {
			return "<\(self.name)>\(text)</\(self.name)>"
		} else {
			return "<\(self.name) />"
		}
	}
	init(name: String, text: String? = nil) {
		self.name = name
		self.text = text
	}
	deinit {
		print("\(name) is being deinitialized")
	}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
// prints"hello, world"

注意: 上面的 paragraph
变量定义为 可选HTMLElement ,因此我们可以赋值 nil 给它来演示循环强引用。

2.解决闭包之间的循环强引用

class HTMLElement {
	let name: String
	let text: String?
	lazy var asHTML: Void -> String = {
		[unowned self] in // 这里加上占有列表
		if let text = self.text {
			return "<\(self.name)>\(text)</\(self.name)>"
		} else {
			return "<\(self.name) />"
		}
	}
	init(name: String, text: String? = nil) {
		self.name = name
		self.text = text
	}
	deinit {
		print("\(name) is being deinitialized")
	}
}

闭包内的捕获定义:

1.无主引用,在闭包和捕获的实例总是互相引用时并且总是同时销毁时

2.弱引用,在被捕获的引用可能会变为 nil 时

定义捕获列表

捕获列表中的每一项都由一对元素组成,一个元素是 weak 或 unowned 关键字,另一个元素是类实例的引用(如 self )或初始化过的变量(如 delegate = self.delegate! )。这些项在方括号中用逗号分开。

如果闭包有参数列表和返回类型,把捕获列表放在它们前面:

lazy var someClosure: (Int, String) -> String = {

[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in

// closure body goes here

}

如果闭包没有指明参数列表或者返回类型,即它们会通过上下文推断,那么可以把捕获列表和关键字 in 放在闭包最开始的地方:

lazy var someClosure: Void -> String = {

[unowned self, weak delegate = self.delegate!] in

// closure body goes here

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 08-25

ARC之解决闭包引起的循环强引用的相关文章

[Swift]Day15:闭包中的循环强引用

闭包中的循环强引用 解决闭包和类实例之间的循环强引用可以通过定义捕获列表来实现. 捕获列表 捕获列表中的每个元素都是由weak或者unowned关键字和实例的引用(如self)成对组成.每一对都在方括号中,通过逗号分开: lazy var someClosure: (Int, String) -> String = { [unowned self] (index: Int, stringToProcess: String) -> String in } 我们需要判断捕获列表中的属性是弱引用还是

Swift - 内存泄露原因(循环强引用)及解决办法

Swift使用自动引用计数(ARC)来管理应用程序的内存使用.在大多是情况下,并不需要考虑内存的管理.当实例不再需要的时候,ARC会自动释放这些实例所使用的内存. 但ARC并不是绝对安全的.下面两种情况会发生内存泄露. 1,类实例之间的循环强引用 两个类实例都有一个强引用指向对方,这样的情况就是强引用循环,从而导致内存泄露. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

Swift-08-闭包引起的循环强引用

循环强引用还会发生在当你将一个闭包赋值给类实例的某个实例,并且这个闭包体中又实用了这个类实例.这个闭包体重可能访问了实例的某个属性,例如self.**,或者闭包中调用了实例的某个方法,例如self.**,这两种情况都导致闭包“捕获”self,从而产生了循环强引用. 循环强引用的产生,是因为闭包和类相似,都是引用类型.当你把闭包赋值给某个属性时,你也把一个引用赋值给了这个闭包.实质上,这跟之前的问题一样,两个强引用让彼此一直有效.但是,和两个类实例不同,这次一个是类实例,另一个是闭包. Swift

block浅析与使用block导致循环强引用举例

定义语法 外部变量值截获 改变外部变量值 block变量作用域导致block体从栈复制到堆同时变量持有了block体中截获的变量 block变量作用域导致强引用 typedef void(^BlockType)(NSString *str);//声明一个void(^)(NSString *str)的block类型,类型名为BlockType-(void)viewDidLoad{ int i=[self getValuesFrom:^int(int i, int y) {//算法由自己定,值由别人

Objective-C 内存管理浅析与循环强引用举例

理解 变量 作用域 变量废弃 持有对象 释放对象 对象所有者(引用计数) 对象废弃 变量所有权修饰符对对象的影响 对象相互持有导致循环强引用,举例如反复执行任务的NSTimer对象的目标对象 又保留了计时器对象,若该NSTimer对象被目标对象持有,便必定会发生循环强引用,因为NSTimer对象会持有目标, 而该NSTimer对象又是目标对象的成员变量也就是目标对象又持有该NSTimer对象 此循环强引用会一直持续到目标对象调用NSTimer对象的invalidate方法释放该NSTimer对象

避免Block中的强引用环

[避免Block中的强引用环] In manual reference counting mode, __block id x; has the effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you cou

shared_ptr造成的循环引用&amp;&amp;解决方法和原理(弱引用&amp;&amp;强引用)

 弱用指针的方式解决shared_ptr造成的循环引用防止内存泄漏! <***>循环引用就是由于智能指针shared_ptr造成的,下面就是shared_ptr的使用造成循环引用的图解: <****>举个例子来说下shared_ptr造成的循环引用: (选题背景双向链表) <span style="font-size:18px;">#include<memory> #include<iostream> using namesp

objective-c启用ARC时的内存管理 (循环引用)

PDF版下载:http://download.csdn.net/detail/cuibo1123/7443125          在Objective-C中,内存的引用计数一直是一个让人比较头疼的问题.尤其是当引用计数涉及到arc.blocks等等的时候.似乎ARC的出现只是让我们解放了双手,由于底层实现依然依赖引用计数,所以开启ARC后,只有对引用计数机制更加了解,才能避免Cycle Retain.Crash等问题的出现. 但是由于使用ARC可以显著提高编码效率,所以建议尽量启用arc,本文

浅谈JS闭包中的循环绑定处理程序

初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript的闭包特性. 前几天工作中写前端js代码时,遇到了遍历元素给它添加单击事件. (PS:之前也在<jQuery基础教程>第四版中看过讲循环绑定处理程序的内容,当时估计也没怎么用心看,所以没记起来.) 大神要是知道这类情况,可以关掉窗口,写这些主要是给像我一样的小白看的,谢谢! 先贴上错误的例子让大家