Swift-08-闭包引起的循环强引用
循环强引用还会发生在当你将一个闭包赋值给类实例的某个实例,并且这个闭包体中又实用了这个类实例。这个闭包体重可能访问了实例的某个属性,例如self.**,或者闭包中调用了实例的某个方法,例如self.**,这两种情况都导致闭包“捕获”self,从而产生了循环强引用。
循环强引用的产生,是因为闭包和类相似,都是引用类型。当你把闭包赋值给某个属性时,你也把一个引用赋值给了这个闭包。实质上,这跟之前的问题一样,两个强引用让彼此一直有效。但是,和两个类实例不同,这次一个是类实例,另一个是闭包。
Swift提供了一种优雅的方法来解决这个问题,称之为闭包捕获列表。
在定义闭包时,同时定义捕获列表作为闭包的一部分,通过这种方式可以解决闭包和类实例之间的循环强引用。捕获列表定义了闭包体内捕获一个或者多个引用类型的规则。跟解决两个类实例间的循环强引用一样,声明每个捕获的引用为弱引用或无主易用,而不是强引用。应该根据代码关系来决定使用弱引用还是无主引用。
----------定义捕获列表
捕获列表中的每一项都由一对元素组成,一个元素是weak或unowned关键字,另一个元素是类实例的引用(如self)或初始化过的变量(如delegate = self.delegate!)。这些项在方括号中用逗号分开。
如果闭包有参数列表和返回类型,把捕获列表放在它们前面:
如果闭包没有指明参数列表或者返回类型,即他们会通过上下文来判断,那么可以把捕获列表和关键字in放在闭包最开始的地方。
----------弱引用和无主引用
在闭包和捕获的实例总是互相引用时并且总是同时销毁时,将闭包内的捕获定义为无主引用。
相反的,在被捕获的引用可能会变为nil时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为nil。这使我们可以在闭包体内检查他们是否存在。
注意:如果被捕获的引用绝对不会变为nil,应该用无主引用,而不是弱引用。
class HTMLElement {
let name:String
let text:String? lazy var asHTML:Void -> String = {
[unowned self] in //表示“用无主引用而不是强引用来捕获 self ”
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())
打印:
<p> hello world<p>
这个闭包这个地方,没有看懂。
Swift-08-闭包引起的循环强引用的更多相关文章
- Swift - 内存泄露原因(循环强引用)及解决办法
Swift使用自动引用计数(ARC)来管理应用程序的内存使用.在大多是情况下,并不需要考虑内存的管理.当实例不再需要的时候,ARC会自动释放这些实例所使用的内存. 但ARC并不是绝对安全的.下面两种情 ...
- Swift 学习笔记 (三) 之循环引用浅析
原创:转载请注明出处 110.自动引用计数实践 下面的例子展示了自动引用计数的工作机制.例子以一个简单的Person类开始,并定义了一个叫name的常量属性: class Person { l ...
- 弱引用?强引用?未持有?额滴神啊-- Swift 引用计数指导
ARC ARC 苹果版本的自动内存管理的编译时间特性.它代表了自动引用计数(Automatic Reference Counting).也就是对于一个对象来说,只有在引用计数为0的情况下内存才会被释放 ...
- Swift 学习- 08 -- 闭包
// 闭包是自包含的函数代码块, 可以在代码中被传递和使用, swift 中的闭包 与 C语言 和 OC 中的代码块 (blocks) 以及其他一些编程语言中的匿名函数比较类似 // 闭包可以捕获和存 ...
- Swift入门(十)——循环引用、弱引用和无主引用
近期看到swift里面不仅有循环引用和弱引用(weak),还加入了无主引用(unowned),于是写了一些demo,这里总结一下. 和OC一样.Swfit默认也是基于ARC进行内存管理的,因此尽管简单 ...
- Swift:闭包(Closures)
一. 基本概念 闭包(Closures)是自包括的功能代码块,能够在代码中使用或者用来作为參数传值. 在Swift中的闭包与C.OC中的blocks和其他编程语言(如C#)中的lambda, java ...
- iOS - Swift Closure 闭包
1.Closure 闭包在 Swift 中非常有用.通俗的解释就是一个 Int 类型里存储着一个整数,一个 String 类型包含着一串字符,同样,闭包是一个包含着函数的类型.有了闭包,你就可以处理很 ...
- Swift的闭包(二):捕获值
闭包可以从定义它的上下文中捕获常量和变量. 在Swift中,捕获值最简单的例子是嵌套函数,举个例子: func makeIncrementer(forIncrement amount: Int) -& ...
- Swift:闭包
一.闭包的介绍 闭包表达式(Closure Expressions) 尾随闭包(Trailing Closures) 值捕获(Capturing Values) 闭包是引用类型(Closures Ar ...
随机推荐
- win8 中实现断点续传
1) Resume method does resume on cases where resume is possible. Meaning if the server accepts range- ...
- FileUpload上传图片直接浏览显示(没有上传按钮如何上传)
1.给FileUpload添加一个onchange事件:FileUpload1.Attributes.Add("onchange", "document.getEleme ...
- 去掉地址栏中的jsessionid
原来我在index.jsp中的编码是 <c:redirect url="/sys/login.shtm"/> 结果每次第一次登录都会在地址栏上出现了jsessionid ...
- DNS服务器的配置与应用: BIND9 的安装与配置
3. BIND9 的安装与配置 3.1 bind简介 BIND (Berkeley Internet Name Domain)是Domain Name System (DNS) 协议的一个实现,提供了 ...
- 【液晶模块系列基础视频】5.1X-GUI字体驱动1
============================= 技术论坛:http://www.eeschool.org 博客地址:http://xiaomagee.cnblogs.com 官方网店:ht ...
- 配置Log4j(很详细)
Log4J的配置文件(Configuration File)就是用来设置记录器的级别.存放器和布局的,它可接key=value格式的设置或xml格式的设置信息.通过配置,可以创建出Log4J的运行环境 ...
- WEB项目web.xml文件中classpath: 跟classpath*:使用的区别
引用一篇很不错的文章:http://blog.csdn.net/wxwzy738/article/details/16983935 首先 classpath是指 WEB-INF文件夹下的classes ...
- 小红伞和virtualbox5.0.10冲突
win7 sp1 64bit 旗舰版:virtual box 5.0.10 提示 error in supr3hardNtChildWaitFor……Timed out after 60001 ms ...
- DS实验题 地鼠安家
★实验任务 fd是一个公认的美丽校园.一天,fd来了一群地鼠,编号为1到n,他们希望在这里定居.现在先由第一只地鼠往下打一个单位的距离,并且在那里安家.对于每一个已经安家的地鼠,如果他左下或右下没有邻 ...
- Grand Theft Auto V 图形研究(3)
原文链接 http://www.adriancourreges.com/blog/2015/11/02/gta-v-graphics-study-part-3/ Post Processing Eff ...