实用内存管理 | 青训营笔记

113 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第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 (nonatomicstrong) Dog *dog;
@property (nonatomiccopyNSString *name;
@property (nonatomicweakid<PersonDelegate> delegate;
@property (nonatomicassignint age;
​

person1强引用dog1 弱引用friend1

friend1指向person1强引用person1

image-20220728215746541

销毁的时候

1⃣️friend1 没有强引用指向自己 (销毁条件是没有强引用指向自己) 所以friend1销毁

image-20220728220115959

2⃣️person1发现没有强引用指向自己 person1销毁

image-20220728220158540

3⃣️dog1发现没有强引用指向自己 dog1销毁

image-20220728220234652

内存回收流程不会发生内存泄漏情况

  • 如果strong delegate
@interface Person : NSObject
...
@property (nonatomic, weak) id<PersonDelegate> delegate;
​
//forbidden!!!!
@property (nonatomic, strong) id<PersonDelegate> delegate;
...
@ end

image-20220728220417273

friend1发现person1强引用指向自己 person1发现friend1强引用指向自己

循环引用 无法销毁 常用把某一个类的代理变成weak 有效避免循环引用

注:同时Block(闭包)中也会出现

浅拷贝/深拷贝 可变/不可变

img

  • 深浅拷贝 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

  1. NSString
  • copy : 对 传入值 进行copy <-[传入值 copy] <-浅拷贝
  • strong : 持有stringA
  1. NSMutableString

可变对象可以直接赋值给不可变对象属性

  • copy : 对 传入值 进行copy <-[传入值 copy] <-[可变对象 copy] 深拷贝
  • strong : 持有stringM

⚠️代码中一般用copy修饰不可变对象?

防止传入可变对象 无论传入 mutable 还是 immutable 都可以保证自己拥有的是 immutable 的副本 初始化后不会被外部修改影响。

  • copy修饰的不可变属性不会随传入值变化
  • strong修饰的不可变属性会随传入值变化

内存问题引起 Crash

野指针

  • 当所指向的对象被提前释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址
  • 若操作系统将这部分已经释放的内存重新分配给另外一个进程
  • 而原来的程序重新引用现在的野指针,则将产生无法预料的后果(此时野指针所指向的内存现在包含的已经完全是不同的数据)

OOM(Out Of Memory)

iOS 设备上当前应用因为内存占用过高而被操作系统强制终止