自动引用计数
来源:互联网 发布:澳大利亚mac口红便宜么 编辑:程序博客网 时间:2024/05/17 06:18
ARC 如何工作
每当你产生一个对象,ARC分配一大块控件去存储这个对象。 除此之外,当一个对象是不在需要,ARC 将会收回这个实例对象所占的空间。 如果一个对象的空间被释放掉,但是你任然通过对象的引用调用方法或者属性,你的程序将要崩溃。 为了不让对象被释放掉 ARC将会追踪有多少属性、常量、变量正在引用这个对象。只要有一个在引用他 ARC 将不会释放这个对象。 因此当年给属性、常量或者变量赋值的时候,应该确保强引用这个对象。例子:class Person { let name: String init(name: String) { self.name = name print("\(name) is being initialized") } deinit { print("\(name) is being deinitialized") }}定义三个变量,因为是可选类型,所以自动赋值为 nilvar reference1: Person?var reference2: Person?var reference3: Person?//引用计数变为1reference1 = Person(name: "John Appleseed")// Prints "John Appleseed is being initialized"//引用计数变为3reference2 = reference1reference3 = reference1//引用计数变为1reference1 = nilreference2 = nil//引用计数变为0reference3 = nil// Prints "John Appleseed is being deinitialized"
循环引用
当两个对象相互强引用对方,将会造成循环引用的情况,这会导致空间浪费。我们可以用弱引用或者打破这种情况。 下面是循环引用的例子:class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { print("\(name) is being deinitialized") }}class Apartment { let unit: String init(unit: String) { self.unit = unit } var tenant: Person? deinit { print("Apartment \(unit) is being deinitialized") }}var john: Person?var unit4A: Apartment?john = Person(name: "John Appleseed")unit4A = Apartment(unit: "4A")引用情况:
john!.apartment = unit4Aunit4A!.tenant = john现在的引用情况:
john = nil unit4A = nil
这样导致了循环引用,导致空间无法释放。
解决两个类的循环引用
Swift 用两种方式来解决循环引用问题既弱引用和无主引用。 弱引用和无主引用确保一个对象在循环引用中没有强引用另一个对象。当一个对象的存在时间小于另一个对象,我们可以用弱引用。当另一个对象有相同的生存时间或者更长我们应该用无主引用来打破这个循环。
弱引用
弱引用不增加对象的引用计数,当引用对象被 ARC 释放的时候,弱引用的值将会变为 nil。因此弱引用应该被声明为变量。要注意的是当 ARC把弱引用变为 nil 的时候,属性观察者不会被调用。class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { print("\(name) is being deinitialized") }}class Apartment { let unit: String init(unit: String) { self.unit = unit } weak var tenant: Person? deinit { print("Apartment \(unit) is being deinitialized") }}var john: Person?var unit4A: Apartment?john = Person(name: "John Appleseed")unit4A = Apartment(unit: "4A")john!.apartment = unit4Aunit4A!.tenant = john
john = nil// Prints "John Appleseed is being deinitialized" unit4A = nil// Prints "Apartment 4A is being deinitialized"
无主引用
无主应用不会增加对象的引用计数,当所引用的对象被释放的时候, ARC 不会吧无主引用变为 nil。因此无主引用不能为可选值class Customer { let name: String var card: CreditCard? init(name: String) { self.name = name } deinit { print("\(name) is being deinitialized") }}class CreditCard { let number: UInt64 unowned let customer: Customer init(number: UInt64, customer: Customer) { self.number = number self.customer = customer } deinit { print("Card #\(number) is being deinitialized") }}var john: Customer?john = Customer(name: "John Appleseed")john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
john = nil// Prints "John Appleseed is being deinitialized"// Prints "Card #1234567890123456 is being deinitialized"
上面是安全的无主引用,我们可以用 unowned(unsafe)来定义不安全的无主引用, 这意味你有责任来保证代码的安全。否则当对象被释放后,你任然用无主引用来引用对象 所在空间,会导致不可预料的错误。
无主引用和含蓄的解包
Person 和 Apartment 列子中的情况是两个互相引用的属性都可以是 nil,因此,我们可以用弱引用。 Customer 和 CreditCard 例子中的情况是其中有一个可以为 nil,因此我们可以用无主引用来打破循环。 但是还有一种情况是两个属性在初始化完成后都不可以为nil,在这种情况下我们可以在一个类设置无主引用,在另一个为类自动解包可选属性。class Country { let name: String var capitalCity: City! init(name: String, capitalName: String) { self.name = name self.capitalCity = City(name: capitalName, country: self) }}class City { let name: String unowned let country: Country init(name: String, country: Country) { self.name = name self.country = country }}var country = Country(name: "Canada", capitalName: "Ottawa")print("\(country.name)'s capital city is called \(country.capitalCity.name)")// Prints "Canada's capital city is called Ottawa"
闭包的强引用循环
当闭包是类的一个属性,并且闭包捕获了这个类本身,那么将会发生循环引用。当在闭包体里引用本实例的属性时,例如 self.someProperty 或者闭包调用一个方法例如 self.someMethod()。上面的情况都会导致闭包捕获本实例对象,导致循环引用。 闭包是一个引用类型,当把闭包赋值给一个属性,那么属性强引用闭包。 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 { print("\(name) is being deinitialized") }}var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")print(paragraph!.asHTML())// Prints "<p>hello, world</p>"
导致了循环引用
解决闭包强引用循环问题
我们可以定义一个捕获列表,来说明闭包和他捕获对象引用的关系。
第一捕获列表
捕获列表的每一项都是 weak 或者unowned 关键字和一个类的实例变量(such as self)或者一个变量的初始化(such as 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}
弱引用和无主引用
当闭包和其捕获的引用将要一直引用彼此并且一同被回收,我们可以用无主引用。相反的,如果一个对象在一些情况下可能成为 nil,用弱引用。
0 0
- 自动引用计数(ARC)
- 自动引用计数(ARC)
- OC自动引用计数
- swift2 自动引用计数
- 第一章 自动引用计数
- swift自动引用计数
- 自动引用计数
- Swift-自动引用计数
- 自动引用计数
- 自动引用计数
- IOS ARC 自动引用计数
- 自动引用计数的实现
- Swift 自动引用计数(十四)
- ARC(自动引用计数)
- Swift(十六、自动引用计数)
- Swift2.1-自动引用计数
- Swift 自动引用计数(ARC)
- Swift的自动引用计数
- android布局的大小设置之一,.fill_paren、wrap_content 、match_parent
- robotframework(RF)数据库之mongodb
- Swift - 实现图片的模糊效果(高斯模糊滤镜)
- 中点分割法 线段与矩形关系的判断 向量
- MySQL内核深度优化
- 自动引用计数
- c#在指定内容中通过正则查找字符
- 树莓派3wiringPi安装以及串口相关调试和配置
- 数组中最长连续序列
- 很久没写文章了。。。
- sprintf的使用
- 王朝 第十一周
- Caffe、TensorFlow、MXnet三个开源库对比
- HTML标签(一)