什么是内存管理?
程序在运行的过程中通常通过以下行为,来增加程序的内存占用:
1.创建一个OC对象
2.定义一个变量
3.调用一个函数或者方法
而一个设备的内存是有限的,每个软件所能占用的内存也是有限的
当程序苏占用的内存见多时,系统就会发出内存警告,这时就得回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象,变量等
如果程序占用内存过大,系统可能会强制关闭程序,造成程序崩溃、闪退现象,影响用户体验
所以,我们需要对内存进行合理的分配内存、清除内存,回收那些不需要再使用的对象,从而保证程序的稳定性。
哪些对象才需要我们进行内存管理呢?
1.任何继承了NSObject的对象需要进行内存管理
2.而其他非对象类型(int\ char\ float\double\ struct\enum等)不需要进行内存管理,原因如下:
a,继承了NSObject的读象的存储在操作系统的堆里边
b.操作系统的堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表
c.非OC对象一般放在操作系统的栈里面
d.操作系统的栈:由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈(先进后出)
int a = 10; //. 栈
int b = 20; // 栈
//. p : 栈
// Person对象(计数器 = 1) : 堆
Person *p = [[Person alloc] init];
// 经过上面的代码后,栈里的变量a\b\p都会被回收
//。但是堆里面的Person对象还会留在内存中,因为它时计数器依然是1
内存管理模型
提供给OC程序员的基本内存管理模型有以下3种:
自动垃圾收集(ios运行环境不支持)
手工引用计数和自动释放池(MRC)
自动引用计数(ARC)
MRC手动管理内存(几乎不用了)
ARC自动管理内存
Automatic Reference Couting,自动引用计数,即ARC,WWDC2011和Ios5所引入的最大的变革和最激动人心的变化。ARC是新的LLVM3.0编译器的一项特性,使用ARC,可以说一举解决老人广大开发者所厌恶的手动内存管理的麻烦。
使用ARC后,系统会检测出何时需要保持对象,何时需要自动释放对象,编译器会关路好对象的内存,会在合适的地方插入retain,release和autorelease,通过生成正确的代码去自动释放或者保持对象。
1.ARC的判断一个对象是否需要释放不是通过引用计数来进行判断的,而是通过强指针来进行判断的。那么什么是强指针?
强指针
默认所有对象的指针变量都是强指针
被_strong修饰的指针
Person *p1 = [[Person alloc] init];
__strong Person *p2 = [[Person alloc] init];
弱指针
被__weak修饰的指针
__weak Person *p = [[Person alloc] init];
ARC如何通过强指针判断?
只要还有一个强指针变量指向对象,对象就会保持在内存中
2.ARC的使用
int main (int argc, const char * argv[]) {
//. 不用写release,main函数执行完毕后p会被自动释放
Person *p = [[Person alloc] init];
return 0;
}
3.ARC的注意点
不允许调用对象的release方法
不允许调用autorelease方法
重写父类的dealloc方法时,不能再调用[super dealloc];
4.ARC下单对象内存管理
//. 局部变量释放对象随之被释放
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
} // 执行到这一行局部变量p释放
// 由于没有强指针指向对象, 所以对象也释放
return 0;
}
//。清空指针对象随之被释放
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
p = nil;
}
return 0;
}
//. 默认清空所有指针都是强指针
int main(int argc, const char *argv[]) {
@autoreleasepool {
//. p1和p2都是强指针
Person *p1 = [[Person alloc] init];
__strong Person *p2 = [[Person alloc] init];
}
return 0;
}
//. 弱指针需要明确说明
// 注意:千万不要使用弱指针保存新创建的对象
//. p1是弱指针,对象会被立即释放
__weak Person *p1 = [[Person alloc] init];
5.ARC下多对象内存管理
ARC和MRC一样,想拥有每个对象必须用强指针保存对象,但是不需要在dealloc方法中release
6.ARC下@property参数
strong:用于OC对象,相当于MRC中的retain
weak:用于OC对象,相当于MRC中的assign
assign:用于基本数据类型,跟MRC中的assign一样
7.ARC下循环引用问题
ARC和MRC一样,如果A拥有B,B也拥有A,那么必须一方使用弱指针
@interface Person : NSObject
@property (nonatomic, strong) Dog *dog;
@end
@interface Dog : NSObject
// 错误写法, 循环引用会导致内存泄露
//@property (nonatomic, strong) Person *owner;
// 正确写法, 当如果保存对象建议使用weak
@property (nonatomic, weak) Person *owner;
@end