objective-c的内存管理划分是基本类型存储在栈内(栈内被占用的内存由系统自动释放),对象存储在堆内。由于objc没有垃圾回收机制(GC) 不能自动释放堆中的内存,需要程序员自己手动释放,否则会导致内存溢出。objc的内存管理机制主要有:1、引用计数器 2、属性参数 3、自动释放池。
1、引用计数器
xcode4.2之后就引入了ARC(Automatic Reference Counting)自动引用计数机制,程序编译时自动给代码添加内存释放代码,因此我们不能再添加释放内存的代码。若想要自己管理内存,则需要将ARC关 闭(在Xcode中关闭ARC:项目属性—Build Settings--搜索“garbage”找到Objective-C Automatic Reference Counting设置为No即可)。
Objc没有垃圾回收机制,所以Objc的内存管理依赖对象引用计数器来进行的。每个对象在创建之后都有一个与之对应的整数(retainCount),即“引用计数器”。对象在创建之后引用计数器为1,在调用对象的copy、retain、alloc、new之后对象的引用计数器都会在原来的基础上再加1,如果调用这个对象的release就会减1,若引用计数器等于0,则系统会调用这个对象的dealloc方法来释放内存,销毁对象。且秉承着“谁创建,谁释放”原则。
2、属性参数?
? 如:@property(nonatomic,strong)Car *car 这样的属性,没有对其进行手动的getter 和setter的方法也不会导致内存泄露。用到属性@property来定义一个实例变量,这样Xcode将会自动的在相应的.m文件中生成setter和getter方法.属性参数是怎么样管理内存的呢?
我们先看当属性为retain时,它的setter内部如何实现的:
-(void)setName:(NSString)name{
if(_name !=name){
[_name release];//先释放原来的值
_name =[name retain];//新值在retain一次再赋值;
}
}
当属性为copy时,它的setter内部如何实现:
-(void)setName:(NSString)name{
if(_name !=name){
[_name release];//先释放原来的值
_name =[name copy];
}
}
属性修饰成copy的setter方法内部实现
getter的方法能够延长对象的生命周期,它的内部代码如下:
-(NSString *)name{
return [[_name retain] autorelease];
}
getter方法的更安全的写法
这以上是系统中生成的setter和getter方法,它保证了内存的能够更好更安全的回收
3、自动释放池?
在ObjC中也有一种内存自动释放的机制叫做“自动释放池”,这是一种半自动的机制,有些操作需要我们手动设置。自 动内存释放使用@autoreleasepool关键字声明一个代码块,如果一个对象在初始化时调用了autorelase方法,那么当代码块执行完之 后,在块中调用过autorelease方法的对象都会自动调用一次release方法。这样一来就起到了自动释放的作用,同时对象的销毁过程也得到了延 迟(统一调用release方法)。