这是我参与「第四届青训营 」笔记创作活动的的第6天。
今天继续整理了上课的系统内存管理部分,学习了实用内存管理部分。
\
实用内存管理
属性@property
属性是类的成员变量 还生成了属性的setter和getter方法
-
strong/weak 只有OC对象才可以使用该属性
- strong 拥有属性对象 强持有 只有我销毁对方才销毁
- weak 不拥有属性对象 弱持有 对方销毁与我无关
-
porperty修饰符 copy(拥有属性对象的拷贝) 修饰不可变对象
- 和 strong 区别: setter 内部会调用 copy 方法
-
assign 制定 setter 使用简单赋值
- 一般用于 simple types 如基本类型/NSInteger/CGRect
- default 修饰符
循环引用
⚠️代理模式中常出现
- weak delegate
//通过alloc init创建person1对象
Person *person1 = [[Person alloc] init];
//创建dog1和f1对象
Dog * dog1 = [Dog new];
Friend *f1 = [Friend new];
//赋值dog属性
person1.dog = dog1;
//赋值代理
person1.delegate = f1;
//f1的myFriend指向person1
f1.myFriend = person1;
@property (nonatomic, strong) Dog *dog;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, weak) id<PersonDelegate> delegate;
@property (nonatomic, assign) int age;
person1强引用dog1 弱引用friend1
friend1指向person1强引用person1
销毁的时候
1⃣️friend1 没有强引用指向自己 (销毁条件是没有强引用指向自己) 所以friend1销毁
2⃣️person1发现没有强引用指向自己 person1销毁
3⃣️dog1发现没有强引用指向自己 dog1销毁
内存回收流程不会发生内存泄漏情况
- 如果strong delegate
@interface Person : NSObject
...
@property (nonatomic, weak) id<PersonDelegate> delegate;
//forbidden!!!!
@property (nonatomic, strong) id<PersonDelegate> delegate;
...
@ end
friend1发现person1强引用指向自己 person1发现friend1强引用指向自己
循环引用 无法销毁 常用把某一个类的代理变成weak 有效避免循环引用
注:同时Block(闭包)中也会出现
浅拷贝/深拷贝 可变/不可变
-
深浅拷贝 deep/shallow copy
- 浅拷贝 指针拷贝 复制一个新的指针 指向同一块内存区域 实际内存没有发生拷贝
- 深拷贝 内容拷贝 指针指向拷贝的数据区
-
两种类/两种行为
- 不可变对象/可变对象
- copy/mutableCopy
-
NSString 不可变对象
- copy 浅拷贝
- mutableCopy 深拷贝 本质是在内存中创建了一个mutableString对象
-
NSMutableString 可变对象
- copy 深拷贝 本质是在内存中创建了一个NSString对象
- mutableCopy 深拷贝 本质是在内存中创建了一个NSMutableString对象
-
传参数时,property的copy/strong 都是浅拷贝
-
NSMutableString * -copy- NSString */NSMutableString *
都是深拷贝 本质是在内存里创建了一个NSString对象
小结:
不可变对象
- copy 【深拷贝】
- mutableCopy【深拷贝】
可变对象
- copy 【深拷贝】
- mutableCopy 【深拷贝】
代码中,深拷贝一般是在转换immutable<=>mutable的时候用到
- [NSString mutableCopy] 会得到深拷贝 string 并且被转换成mutable
- [NSMutableString copy] 会得到深拷贝 string 并且被转换成immutable
mutableCopy 总是深拷贝,会生成新的可变对象
property的copy/strong
- NSString
- copy : 对 传入值 进行copy <-[传入值 copy] <-浅拷贝
- strong : 持有stringA
- NSMutableString
可变对象可以直接赋值给不可变对象属性
- copy : 对 传入值 进行copy <-[传入值 copy] <-[可变对象 copy] 深拷贝
- strong : 持有stringM
⚠️代码中一般用copy修饰不可变对象?
防止传入可变对象 无论传入 mutable 还是 immutable 都可以保证自己拥有的是 immutable 的副本 初始化后不会被外部修改影响。
- copy修饰的不可变属性不会随传入值变化
- strong修饰的不可变属性会随传入值变化
内存问题引起 Crash
野指针
- 当所指向的对象被提前释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址
- 若操作系统将这部分已经释放的内存重新分配给另外一个进程
- 而原来的程序重新引用现在的野指针,则将产生无法预料的后果(此时野指针所指向的内存现在包含的已经完全是不同的数据)
OOM(Out Of Memory)
iOS 设备上当前应用因为内存占用过高而被操作系统强制终止