Swift中的ARC(Automatic Reference Counting)
2017-06-07 17:26
459 查看
first of all参考文档
另外,当不再需要实例时,ARC会释放该实例使用的内存,以便于将内存用于其他目的,这样可以确保类实例在不再需要时不占用内存空间,
但是,如果ARC要释放仍在使用的实例,那么将无法在访问该实例的属性,或者调用该实例的方法,实际上,如果你尝试访问该实例,那么您的应用程序很可能会崩溃。
为了确保实例在仍然需要时不会消失,ARC跟踪当前引用每个类实例的属性,常量和变量,只要至少对该实例的一个活动引用仍然存在,ARC将不会释放实例。
为了实现这一点,只要将类实例分配给属性(常量或者变量),该属性(常量或者变量)就可以强制引用该实例,这个应用被称为“强”引用,因为它保持了对该实例的坚定的约束,并且不允许它被接触分配,只要这种强烈的计数依然存在,
去实例化这个类并且进行多次引用
运行完成之后的打印情况
在以上的示例中,ARC能够跟踪Person创建的实例的引用数量,如果不再需要时,就给Person类的实例释放掉
Apartment类
Person类
需要注意:Person类的apartment是可选的,Apartment的tenant属性也是可选的(即:是可以用weak来修饰的)
在控制器里面声明了两个属性并且实例化之后,对实例的引用情况如下
当john有一个公寓,并且公寓有一个租客是john时,就会造成两个实例的循环引用
如图:
这时候,Person实例对Apartment的实例有抢引用,Apartment的实例对Person的实例有一个强引用,因此,就算你断开了john和unit4A变量所持有的强引用时,引用计数也不会下降到0,并且实例不会被ARC释放内存
效果如图:
在Apartment类里面的tenant属性前面加上weak关键字
在控制器里面注释掉两行代码
此时的引用情况如下
打印结果:
打印结果:
此时:之前循环引用的对象就被全部释放了,但是,以上不管是Apartment的tenant属性还是Person的unit属性,都是可变的,也就是可以用weak来修饰的, 那如果属性不是可变的,该怎么办呢?—当当当当 未引用(unowned)登场
例如:定义两个类,Customer(客户)以及CreditCard(信用卡)
客户可能没有信用卡,但是信用卡一定会关联一个客户,所以客户里面的信用卡类型的属性是可选的,但是信用卡里面的客户是必选的
类Customer
类CreditCard
在控制器里实例化一个客户的对象,然后通过信用卡的实例化,给客户的信用卡赋值
相互引用如下
该Customer实例现在对CreditCard有强引用,并且该CreditCard实例对Customer的实例未引用(用了unowned关键字修饰了),所以当打破john变量所持有的强引用时,Customer就没有强引用了,所以如果Customer的实例会被释放,当Customer实例被释放了以后,CreditCard的实例也没有强引用了,也会被释放
此时的引用情况如下:
运行结果如下:
ARC(自动引用计数)
Swift使用”自动引用计数(Automatic Reference Counting)”来跟踪和管理引用程序中的内存使用情况。在大多数情况下,这意味着在Swift中内存不需要你自己来管理,当有些实例对象不再需要时(引用计数为0),ARC会自动释放实例对象使用的内存ARC如何工作
每次创建一个类的新实例时,ARC会分配一大块内存来存储有关该实例的信息,该内存将保存有关实例类型的信息,已经与该实例关联的任何存储属性的值另外,当不再需要实例时,ARC会释放该实例使用的内存,以便于将内存用于其他目的,这样可以确保类实例在不再需要时不占用内存空间,
但是,如果ARC要释放仍在使用的实例,那么将无法在访问该实例的属性,或者调用该实例的方法,实际上,如果你尝试访问该实例,那么您的应用程序很可能会崩溃。
为了确保实例在仍然需要时不会消失,ARC跟踪当前引用每个类实例的属性,常量和变量,只要至少对该实例的一个活动引用仍然存在,ARC将不会释放实例。
为了实现这一点,只要将类实例分配给属性(常量或者变量),该属性(常量或者变量)就可以强制引用该实例,这个应用被称为“强”引用,因为它保持了对该实例的坚定的约束,并且不允许它被接触分配,只要这种强烈的计数依然存在,
举例
1:引用计数为0或者不为0时的验证
首先新建一个Person类import Foundation class Person { let name: String init(name: String) { self.name = name print("Person类被实例化了") } deinit { print("Person对象被销毁了") } }
去实例化这个类并且进行多次引用
import UIKit class ViewController: UIViewController { var reference1: Person? var reference2: Person? var reference3: Person? override func viewDidLoad() { super.viewDidLoad() reference1 = Person(name: "lausen") reference2 = reference1 reference3 = reference1 reference1 = nil reference2 = nil reference3 = nil } }
运行完成之后的打印情况
在以上的示例中,ARC能够跟踪Person创建的实例的引用数量,如果不再需要时,就给Person类的实例释放掉
2:两个类的实例之间的循环引用
新建一个Apartment类,Apartment类里面有一个Person类型的tenant属性,给上述的 Person类添加一个Apartment类型的apartment的属性,Apartment类
import Foundation class Apartment { let unit: String var tenant: Person? init(unit: String) { self.unit = unit } deinit { print("Apartment对象被释放了") } }
Person类
import Foundation class Person { let name: String var apartment: Apartment? init(name: String) { self.name = name print("Person类被实例化了") } deinit { print("Person对象被销毁了") } }
需要注意:Person类的apartment是可选的,Apartment的tenant属性也是可选的(即:是可以用weak来修饰的)
import UIKit class ViewController: UIViewController { var john: Person? var unit4A: Apartment? override func viewDidLoad() { super.viewDidLoad() john = Person(name: "John Appleseed") unit4A = Apartment(unit: "4A") } }
在控制器里面声明了两个属性并且实例化之后,对实例的引用情况如下
当john有一个公寓,并且公寓有一个租客是john时,就会造成两个实例的循环引用
import UIKit class ViewController: UIViewController { var john: Person? var unit4A: Apartment? override func viewDidLoad() { super.viewDidLoad() john = Person(name: "John Appleseed") unit4A = Apartment(unit: "4A") //两个实例进行循环引用 john?.apartment = unit4A unit4A?.tenant = john } }
如图:
这时候,Person实例对Apartment的实例有抢引用,Apartment的实例对Person的实例有一个强引用,因此,就算你断开了john和unit4A变量所持有的强引用时,引用计数也不会下降到0,并且实例不会被ARC释放内存
//即使赋值为nil,控制台也不会打印对象被释放的信息 john = nil unit4A = nil
效果如图:
解决类实例之间的强引用循环
Swift提供了两种方法来解决强引用循环,若引用(weak)和未引用(unowned)2.1 弱引用(weak)
一个弱引用不会对实例进行强引用,此行为可防止引用成为引用循环的一部分,在属性前面放置一个weak来声明一个若引用,因为一个弱引用并没有对它引用的实例保持强烈的控制,所以这个实例是可以被释放的,在Apartment类里面的tenant属性前面加上weak关键字
//用weak修饰属性,对象就不会对该属性进行强引用 weak var tenant: Person?
在控制器里面注释掉两行代码
//即使赋值为nil,控制台也不会打印对象被释放的信息 // john = nil // unit4A = nil
此时的引用情况如下
john = nil
打印结果:
unit4A = nil
打印结果:
此时:之前循环引用的对象就被全部释放了,但是,以上不管是Apartment的tenant属性还是Person的unit属性,都是可变的,也就是可以用weak来修饰的, 那如果属性不是可变的,该怎么办呢?—当当当当 未引用(unowned)登场
2.2 未引用(unowned)
想弱引用一样,一个无名的参考并不能保持对它所指的实例的强烈的控制,但是,与弱引用不同,当另一个实例具有相同的声明周期或者更长的声明周期时,将使用位置引用,您可以通过unowned关键字放在属性或变量声明之前来指示位置引用例如:定义两个类,Customer(客户)以及CreditCard(信用卡)
客户可能没有信用卡,但是信用卡一定会关联一个客户,所以客户里面的信用卡类型的属性是可选的,但是信用卡里面的客户是必选的
类Customer
import Foundation class Customer { /// 消费者的名字 let name: String /// 消费者手里的信用卡 var card: CreditCard? init(name: String) { self.name = name } deinit { print("消费者的实例对象被释放了") } }
类CreditCard
import Foundation class CreditCard{ let number: Int64 unowned let customer: Customer init(num: Int64,customer: Customer) { self.number = num self.customer = customer } deinit { print("信用卡的实例对象被释放了") } }
在控制器里实例化一个客户的对象,然后通过信用卡的实例化,给客户的信用卡赋值
import UIKit class ViewController: UIViewController { var john: Customer? override func viewDidLoad() { super.viewDidLoad() john = Customer(name: "john Appleseed") john?.card = CreditCard(num: 1234_5678_9012_3456, customer: john!) } }
相互引用如下
该Customer实例现在对CreditCard有强引用,并且该CreditCard实例对Customer的实例未引用(用了unowned关键字修饰了),所以当打破john变量所持有的强引用时,Customer就没有强引用了,所以如果Customer的实例会被释放,当Customer实例被释放了以后,CreditCard的实例也没有强引用了,也会被释放
//当变量john不引用Customer的实例的时候,Customer的实例就会被释放 john = nil
此时的引用情况如下:
运行结果如下:
相关文章推荐
- Swift 自动引用计数(Automatic Reference Counting, ARC)
- ARC专题:Xcode 4.2 中的Automatic Reference Counting (ARC)转
- 如何在项目中开始使用ARC(Automatic Reference Counting)
- 【转】ARC(Automatic Reference Counting )技术概述
- ARC(Automatic Reference Counting )技术概述
- ARC专题:再续 Xcode 4.2 中的Automatic Reference Counting (ARC)
- 【iOS开发】JSONKit does not support Objective-C Automatic Reference Counting(ARC)
- 寒城攻略:Listo 教你 25 天学会 Swift 语言 - 18 Automatic Reference Counting
- Xcode编译器特性:ARC(Automatic Reference Counting)
- ARC(Automatic Reference Counting )技术概述
- 自动引用计数(ARC Automatic Reference Counting)
- Xcode 5 如何禁用某个文件ARC(Automatic Reference Counting)
- ARC(Automatic Reference Counting )技术概述
- Automatic Reference Counting(ARC)特性学习(iOS5新特性学习之五)
- Automatic Reference Counting (ARC)
- Automatic Reference Counting (ARC) 自动引用计数
- Automatic Reference Counting (ARC) 总结
- ARC(Automatic Reference Counting )技术概述(转)
- IOS开发之---ARC(Automatic Reference Counting)
- 回归基础:重温 Automatic Reference Counting (ARC)