一、IOS内存管理
1、内存管理范围:任何继承了NSObject的对象,对基本数据类型无效。
2、内存管理原理:
(1)每个对象内部保存了一个与之相关联的整数,称为引用计数器。
(2)当使用alloca、new或者copy创建一个对象时,对象的引用计数器被设置为1.
(3)当给对象发送一条retain消息时,引用计数器加。
(4)当给对象发送一条release消息时,引用计数器减1。
(5)当对象的引用计数器为0时,该对象将被销毁,其占用的内存将被系统回收,OC也会自动向对象发送一条dealloc消息。一般会重写dealloca方法来释放相关资源,一定不要直接调用dealloca方法。
(6)可以给对象发送retainCount消息获得当前的引用计数器的值。
用于理解内存管理的实例:
1.Book类:
#import <Foundation/Foundation.h> @interface YtsBook : NSObject { int _ID; } @property int ID; -(id)initWithID:(int)_ID; @end #import "YtsBook.h" @implement YtsBook: @synthesize ID = _ID; -(id)initWithID:(int)ID: { _ID=ID; } @end
2.Student类:
#import <Foundation/Foundation.h> //#import "YtsBook.h" @class YtsBook; //@class声明需用到YtsBook类 @interface YtsStudent : NSObject { YtsBook *_book; } @property YtsBook *book; @end #import "YtsStudent.h" #import "YtsBook.h" @implement YtsStudent: @synthesize book = _book; -(void)setBook:(Book *)book //在OC2.0以上,一般都是用@property的声明列表来代替这种方法。 { if(_book!=book) //加上判断,预防重复复制 { [_book release]; //释放旧值 _book = [book retain]; //先retain,再赋值 } } -(void)dealloc { [_book release]; //由于赋值时做了retain,这里要负责将其release [super dealloc]; }
3. main.m
int main (int argc, const char * argv[]) { @autoreleasepool{ YtsStudent *student = [[YtsStudent alloc] init]; //student引用计数器为1 YtsBook *book = [[YtsBook alloc] initWithID:100]; //book引用计数器为1. student.book = book; //book引用计数器为2 [book release]; //book引用计数器为1 [student release]; //此时book引用计数器为0,student引用计数器为0 } }
二、内存自动释放
1、自动释放池原理
(1)autorelease pool的真名是NSAutoreleasePool,在新建一个项目时,编译器会默认创建一个自动释放池。
(2)NSAutoreleasePool内部包含一个可变数组(NSMutableArray),用于保存声明为autorelease的对象。
(3)如果一个对象声明为autorelease,则系统就将这个对象加入到该数组中。
(4)当NSAutoreleasePool自身在销毁时,会遍历一遍该数组,release数组中的每一个成员。
实例:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; YtsStudent *student = [[[YtsStudent alloc] init] autorelease]; //设置为autorelease YtsBook *book = [[[Book alloc] init] autorelease]; //设置为autorelease student.book = book; [pool release];
2、自动释放池做法
因为标记为autorelease的对象只有在自动释放池被销毁时才被release,当有大量标记为autorelease的对象时,就会存在内存故障。 所以我们经常手动定义一个NSAutoreleasePool,通过控制该池的销毁达到及时释放内存的目的。
创建自动释放池的方法为:NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
销毁自动释放池的方法为:[pool release];
3.当一个对象被声明为autorelease时,它将被加入到最新创建的自动释放池中。
三、内存管理口诀
1. 通过alloc、new或copy创建的对象,那么必须调用release或autorelease。
如果在类的某函数中alloc生成一个对象,那么必须在类的dealloc方法中release该对象,或者alloc和init该对象时就声明autorelease。
注意:实现NSCopying的initWithZone方法里边,不要对创建的对象做autorelease或者release。
2. 除了alloc、new或copy之外的方法创建的系统自带的类的对象都已被声明了autorelease,无需在进行release。