下列行为会增加一个app的内存应用
- 创建一个OC对象
- 定义一个变量
- 调用一个函数或者方法
内存管理,涉及的操作:
- 分配内存:如创建一个对象,会增加内存占用
- 清除内存:如销毁一个对象,能减小内存占用
内存管理的
管理范围
- 任何继承了NSObject的对象
- 对其它非对象类型无效(int, char, float, double, struct, enum等)
只有OC对象才需要进行内存管理的本质原因
- Objective-C对象存放于堆里面
- 非OC对象一般放在栈里面,而栈内存由系统自动管理
引用计数器:4字节
- 每个OC对象都有自己的引用计数器
- 是一个整数
- 可理解为“对象被引用的次数”
- 可理解为“有多少人正在用这个对象”
引用计数器常见操作
- 当用alloc, new 或者 copy创建一个对象时,默认为1
- 给对象发送一条retain消息,引用计数器值+1 (retain方法返回对象本身)
- 给对象发送一条release消息,引用计数器值-1
- 给对象发送一条retainCount消息,获得当前的引用计数器值
- 注意:release并不代表对象被销毁,仅仅是计数器-1
dealloc
- 当对象的引用计数器为0时,系统会自动给对象发送一条dealloc消息,对象被销毁,内存被回收
- 一般会重写dealloc方法,在这里释放相关资源,最后要记得调用[super dealloc];
- 不能自己手动调用dealloc方法
野指针 vs. 空指针
- 僵尸对象:已经被销毁的对象
- 野指针:指向僵尸对象(不可用内存)的指针;给野指针发消息会报EXC_BAD_ACCESS错误
- 空指针:指向nil,给nil发消息没有任何反应,也不会崩溃
- 避免指向野指针:在对象被销毁后,将指向对象的指针变为空指针。
内存管理原则:
- 谁创建谁release
- 谁retain谁release
- 总结:有加就有减
set方法的内存管理
-(void) setSomething:(Something *) something {
if (something != _something) {
[_something release];
_something = [something retain];
}
}
dealloc方法的内存管理
-(void) dealloc {
[_something release];
[super dealloc];
}
@property参数
控制set方法的内存管理
- retain: release 旧值,retain新值 (用于OC对象)
- assign: 直接赋值,不做任何内存管理(默认,用于非OC对象)
- copy: release旧值,copy新值(一般用于NSString *)
控制需不要生成set方法
- readwrite: 同时生成set方法和get方法(默认)
- readonly: 只会生成get方法
多线程管理
- atomic: 性能低(默认)
- nonatomic:性能高
循环retain
- A对象retain了B对象,B对象retain了A对象
- 弊端:导致A, B对象永远无法释放
- 解决方案:当两端相互引用时,一端用retain, 一端用assign
autorelease基本作用
- 给对象发送一条autorelease消息,会将对象放到一个自动释放池中
- 当自动释放池被销毁时,会对池子里的所有对象做一次release操作
- 会返回对象本身
- 调用完autorelease方法后,对象的计数器不变
autorelease的好处
- 不用再关心对象的释放时间
- 不用再关心什么时候调用release
autorelease的使用注意
- 占用内存较大的对象不要随便使用autorelease
- 占用内存较小的对象使用autorelease,没有太大影响
- 一般可以为类添加一个快速创建对象的类方法
- + (instancetype) object { return [[[self alloc] init] autorelese]; }
- 一般来说,除了alloc, new, 或copy 之外的方法创建的对象都被声明了autorelease
自动释放池
autoreleasepool{ }
- 自动释放池以栈结构存在(先进后出)
- 当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池
- 自动释放池的创建方式:autoreleasepool{ }