Swift学习笔记十五
自动引用计数(Automatic Reference Counting)
和OC一样,Swift用自动引用计数机制来跟踪和管理你应用程序的内存,大多数情况下,你不需要考虑自己管理内存,Swift会自动帮你管理。当实例对象不再需要时,Swift会自动释放它使用的内存。但是,在有些情况下,ARC需要知道更多你代码之间的关系来帮助你管理内存,本章会描述那些情况并展示如何启用ARC来管理你应用程序的内存。
注意:引用计数只作用于类实例,结构体和枚举是值类型而非引用类型,并且不是以引用形式被存储和传递的。
每当你创建一个新的类实例对象,ARC为它分配一块内存用以存储比如实例类型、实例相关联的存储式属性的值等。当实例不再被需要时,ARC会销毁实例,释放其所占用的内存以供他用。如果实例已经被销毁,那么就不能再使用它或者访问它的属性、方法。为了确保还被需要的实例不被销毁,ARC追踪有多少属性、常量及变量引用到了一个类实例,只要还有至少一个引用指向实例,ARC就不会销毁它。这是通过“强引用”实现的,当你将一个实例赋值给一个常量或者变量、属性时,那个常量或者变量、属性会与实例之间建立一个“强引用”,之所以成为“强”,是因为这个引用会只要这个引用还存在,那么这个实例就不能被释放销毁。
“强引用”在带来便利的时候,会产生一个问题,就是“强引用循环”,比如实例A的某个属性引用了实例B,而实例B的某个属性又引用了A,那么即使其他任何变量都没有引用A和B,他们也各自被一个强引用持有,那么即便他们都不再被需要,它们也不会被销毁,这就造成了内存泄露。
为了解决个这个问题,可以使用“弱引用(weak reference)”和“不持有引用(unowned reference)”。它们可以使你在引用某个实例对象的时候不会持有它,这样实例在互相引用的时候就不会产生强引用循环。
当引用在其生命周期内的某个时刻可能会是nil的时候,使用“弱引用”,当你确定某个引用在其生命周期内都不可能是nil的时候,使用“不持有引用”。因为弱引用是允许没有值的,因此它只能被赋值给可选类型(optional type)。
“弱引用”只能赋值给变量,不能赋值给常量,这是为了表明在运行时其值可能会发生变化的,当弱引用指向的对象已经被销毁时,ARC将弱引用的值改为nil。比如:
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { println("\(name) is being deinitialized") }
} class Apartment {
let number: Int
init(number: Int) { self.number = number }
weak var tenant: Person? //这里通过weak前缀来声明弱引用变量属性
deinit { println("Apartment #\(number) is being deinitialized") }
}
“不持有引用”和“弱引用”类似,不过它确保永远有值,因此,它总是被赋值给非可选类型,在访问它的时候,也不需要像可选类型那样展开,而是直接访问。此外,当其指向的对象已经被释放时,ARC不能将“不持有引用”设为nil,因为非可选类型的变量不能被设置为nil。事实上,当你访问一个指向已经被销毁对象的不持有引用时,会触发一个运行时错误。
当把一个闭包赋值给一个实例对象的属性,而闭包内部又引用这个实例时(比如闭包体访问实例的属性值self.property或者访问实例的方法self.method),也会发生“强引用循环”,这是因为闭包和类一样,是引用类型的。Swift提供一种优雅的方式来打破这种“强引用循环”,比如:
class HTMLElement { let name: String
let text: String? lazy var asHTML: () -> 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 {
println("\(name) is being deinitialized")
} }
这里HTMLElement类定义了一个lazy属性asHTML,它的默认值是一个闭包,因为它是属性而不是方法,因此你可以用自定义的函数或者闭包来取代默认值,这里属性被标记为lazy,因为它不需要在一开始就被赋值,只有在需要的时候(即需要生成HTML代码),才会执行这个闭包。正因为它是lazy的属性,因此在闭包体内可以访问self,因为执行它的时候初始化已经完成了。
要解决闭包的强引用循环问题,需要用到“捕获列表”,在定义闭包的时候同时定义其捕获列表,这个列表定义了闭包体内捕获一个或多个引用类型时所遵循的规则。
捕获列表是用一堆中括号定义,其内部的项用逗号隔开,每一个项都是一个关键字(weak或unowned)与一个类实例引用(或者一个变量的定义)组成的对,将捕获列表放在其参数列表之前,如下:
lazy var someClosure: (Int, String) -> String = {
[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
// closure body goes here
}
这样就解除了闭包和实例对象之间的强引用循环。
Swift学习笔记十五的更多相关文章
- Swift 学习笔记十五:扩展
扩展就是向一个已有的类.结构体或枚举类型加入新功能(functionality).扩展和 Objective-C 中的分类(categories)相似.(只是与Objective-C不同的是,Swif ...
- python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...
- (转载)西门子PLC学习笔记十五-(数据块及数据访问方式)
一.数据块 数据块是在S7 CPU的存储器中定义的,用户可以定义多了数据块,但是CPU对数据块数量及数据总量是有限制的. 数据块与临时数据不同,当逻辑块执行结束或数据块关闭,数据块中的数据是会保留住的 ...
- (C/C++学习笔记) 十五. 构造数据类型
十五. 构造数据类型 ● 构造数据类型概念 Structured data types 构造数据类型 结构体(structure), 联合体/共用体 (union), 枚举类型(enumeration ...
- Swift学习笔记十六:协议
Protocol(协议)用于统一方法和属性的名称,而不实现不论什么功能. 协议可以被类.枚举.结构体实现.满足协议要求的类,枚举,结构体被称为协议的遵循者. 遵循者须要提供协议指定的成员,如属性,方法 ...
- swift学习第十五天:闭包
闭包 闭包的介绍 闭包和OC中的block非常相似 OC中的block是匿名的函数 Swift中的闭包是一个特殊的函数 block和闭包都经常用于回调 注意:闭包和block一样,第一次使用时可能不习 ...
- MySQL学习笔记十五:优化(2)
一.数据库性能评测关键指标 1.IOPS:每秒处理的IO请求次数,这跟磁盘硬件相关,DBA不能左右,但推荐使用SSD. 2.QPS:每秒查询次数,可以使用show status或mysqladmin ...
- Swift学习笔记十四
Deinitialization 当类的实例对象即将要被释放时,会立即调用deinitializer,通过deinit关键字来定义deinitializer,和initializer一样,它也只存在于 ...
- Swift学习笔记十二
方法 方法就是和某种特定类型相关联的函数.类.结构体.枚举都可以定义实例方法和类型方法.类型方法和OC中的类方法类似. 结构体和枚举也可以定义方法是Swift与C/OC之间很大的一个区别,在OC中,只 ...
随机推荐
- hdu 3478(判断奇环)
题意:给你一个无向图,问你有没有可能存在一个奇环连接所有的节点. 分析:好久没写博客了,这个好习惯还是要继续保持的!这道题通过转化之后就是问你有没有存在一个奇环连接所有的节点,这里用到的方法是染色法, ...
- python27+django1.9创建app的视图及实现动态页面
一.简易静态视图 views文件里写: from django.http import HttpResponse def hello(request): return HttpResponse(&qu ...
- 容器的范围 .xml
pre{ line-height:1; color:#f0caa6; background-color:#2d161d; font-size:16px;}.sysFunc{color:#e54ae9; ...
- git 换行符问题
git 换行符问题 在windows环境中 对于autocrlf = false 不会激发 关于换行符的处理 对于autocrlf = true 会在提交是将LF替换成CRLF 切出时时CRLF 对于 ...
- 简易nagios安装出现的问题及解决方法
安装时候所遇到的问题: A 安装PHP的时候报错xml2-config未找到 安装PHP的时候报错:未找到包libxml2 解决方法:安装libxml2包即可,libxml2是php的依赖包,从而需要 ...
- jQuery hover demo
先放效果图: 百度云下载地址:http://pan.baidu.com/s/1dDpn1Sl 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTM ...
- Python学习第二天数组
1:Python定义数组:a=[0,1,2,3,4] ; 打印数组list(a); 这时:a[0]=0, a[1]=1, a[[2]=2...... 1.1:如果想定义一个很长的数组可以用到pyt ...
- 3Com Network Supervisor与IBM Tivoli NetView两款网管软件操作视频
3Com Network Supervisor与IBM Tivoli NetView两款网管软件操作视频 网管软件必须能够实实在在的给我们带来好处,对于企业网络管理来说,其作用体现在以下几个方面: ...
- ef6 code first
http://www.cnblogs.com/Bce-/p/3684643.html http://www.cnblogs.com/Gyoung/tag/Entity%20Framework/ htt ...
- 第二百三十四天 how can I 坚持
今天果然不负众望,下了一天的雪啊,挺好. 今天把花搞了下,都弄花盆里了,希望不会就这么挂掉.八千代,绿萝,还有小叶元宝. 中午喝了点酒,没感觉. 过两天气温就零下十多度了,该咋办啊,最怕冬天.家里现在 ...