Swift内存管理:管理引用类型的内存,不会管理值类型,值类型不需要管理。
内存管理原则:当没有任何强引用指向对象,系统会自动销毁对象(默认情况下所有的引用都是强引用)
通常情况下我们不需要去手动释放内存,因为ARC会在对象不再被引用,会自动销毁对象,但是有些时候还是需要在代码中实现内存管理
1 | class Person { |
weak弱引用
1 | class Person { |
unowned无主引用
unowned无主引用,相当于OC unsafe_unretained
unowned和weak的区别:
- 利用unowned修饰的变量,对象释放后不会设置为nil,不安全。利用weak修饰的变量,对象释放后会设置nil
- 利用unowned修饰的变量,不是可选类型。利用weak修饰的变量,是可选类型
1 | class Person { |
weak&unowned使用场景
weak1
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
33
34
35
36
37
38class Apartment {
let number:Int // 房间号
var tenant:Person1? // 租客
init(number:Int) {
self.number = number
}
deinit {
print("\(self.number) deinit")
}
}
class Person1 {
let name:String // 姓名
weak var apartment:Apartment? // 公寓
init(name:String) {
self.name = name
}
deinit {
print("\(self.name) deinit")
}
}
var person1:Person1? = Person1(name: "daisuke")
var apartment:Apartment? = Apartment(number: 888)
// 人有一套公寓
person1?.apartment = apartment
// 公寓中住着一个人
apartment?.tenant = person1
person1 = nil
apartment = nil
// 两个对象没有被销毁,内存泄漏
// 在Person1类中apartment属性前添加weak修饰:weak var apartment:Apartment?
// 那么两个对象就被销毁
//888 deinit
//daisuke deinit
unowned
1 | class Card { |
那么总结一下:
- 使用weak和unowned都可以避免循环引用
- 使用weak修饰变量,对象被释放后自动设置为nil,安全
- 使用unowned修饰变量,对象被释放后不能设置nil,因为不是可选类型不能设置nil,不安全
- 使用unowned修饰的变量,一定要有值,所以当场景需要变量必须有值得时候,使用unowned修饰
- 使用weak修饰变量,是可选类型,可有值可没有值
闭包引起的循环引用
循环引用:当一个闭包赋值给对象的某个属性,并且这个闭包体中又使用了对象。这个闭包体可能访问了对象的属性,例如:self.someProperty,或者闭包中调用了对象的方法,例如:self.someMethod。这两种情况都导致闭包==捕获==self,从而引起循环引用。
Swift中的闭包循环引用相当于在OC中的block中使用self。
回顾OC中的block循环引用
1 | // 引起循环引用 |
那么Swift呢?
1 | class Person3 { |
总结:
- 当闭包和捕获的对象总是同时互相引用,并且总是同时销毁的,将闭包内的捕获定义为无主引用unowned
- 相反,当捕获引用是可能会是nil,将闭包内的捕获定义为弱引用weak
- 如果捕获的引用绝对不会置nil,应该使用wnowned,而不是weak
参考: