手动内存管理
OC可用内存回收机制有如下3种:
- 手动引用计数和自动释放池
- 自动引用计数(ARC——Automatic Reference Counting)
- 自动垃圾回收
PS: IOS只支持前两者,另外需要注意的是,OC中的内存管理机制是统计引用计数,当引用计数为0时会触发对象的dealloc方法来销毁对象,从而释放内存。
引用计数方法:
- -retain: 将该对象的引用计数器+1
- -release: 将该对象的引用计数器-1
- -autorelease: 不改变对象的引用计数器的值,只是将对象添加到自动释放池中
- retainCount: 返回该对象的引用计数的值
//接口部分忽略,自行编写,以下为实现部分
@implementation MyUser
- (void) setItem:(MyItem*) item
{
if(_item != item)
//将_item原引用的实例计数器-1,此处主要考虑到更新值时的逻辑
[_item release]
//新实例item计数器+1
[item retain];
_item = item; //也可用 _item = [item retain]
}
- (void) dealloc //重写MyUser的dealloc方法
{
//销毁MyUser实例时,将item的计数器-1,以销毁item对象
[item release];
[super dealloc];
}
使用自动释放池
MyItem* productItem()
{
MyItem* item = [MyItem new]; //引用计数为1
NSLog(@"函数返回之前的引用计数:%ld", item.retainCount);
//autorelease不会改变对象的引用计数,但程序执行autorelease时会将该对象添加到自动释放池中
return [item autorelease];
}
int main(int argh, char* argv[])
{
//定义自动释放池pool
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
//通过productItem()函数获得MyItem对象,由于productItem()函数中将对象放入了自动释放池中,所以此处返回值成功,it的计数器为1
MyItem* it = productItem();
NSLog(@"it的引用计数为:%ld", it.retainCount);
//创建一个MyUser对象病添加到自动释放池中
MyUser* user = [[[MyUser alloc] init] autorelease];
NSLog(@"%ld", user.retainCount);
[pool release]; //释放自动释放池pool
}
临时对象
Foundation类中,当调用方法创建对象时,若不是以alloc、new、copy、mutableCopy开头的,系统都会默认创建自动释放的对象,这些对象会在释放自动释放池时,自动释放,被称为临时对象。
如果程序需要在事件处理结束之后依然保留临时对象:
- 将临时对象赋值前,用retain方法使引用计数+1
- 把临时对象赋值给retain、strong、copy修饰的属性
手动管理内存的规则总结
- 调用release方法不是销毁对象,只是将计数-1,当对象的引用计数为0时,系统会自动调用该对象的dealloc方法来销毁该对象
- 当自动释放池回收时,会依次调用池中每个对象的release方法来使其引用计数-1,之后若引用计数为0则销毁,若大于0则会存活下来
- 当程序使用alloc、new。copy、mutableCopy开头的方法创建对象后,该对象的引用计数为1,当不再使用该对象时,需要调用该对象的release火autorelease方法
- 对象的retain和release方法的调用次数应该相等
- 对于临时对象,多想在释放自动释放池之后保留临时对象,则需要手动调用retain来增加该临时对象的引用计数,或者将该临时对象赋值给retain、strong、copy修饰的属性
自动引用计数
启用ARC,并用 -fobjc-arc 编译,系统会自动管理好内存。
@autoreleasepool{} 块中都会有ARC来自动释放
本文介绍了Objective-C中的三种内存回收机制:手动引用计数、自动引用计数(ARC)及自动垃圾回收。重点讲解了手动引用计数的具体实现,包括retain、release、autorelease等方法的使用,以及自动释放池的作用。

被折叠的 条评论
为什么被折叠?



