Objective-C之成魔之路【17-内存管理】
郝萌主倾心贡献,尊重作者的劳动成果,请勿转载。
我们提供的服务有:网站建设、成都做网站、微信公众号开发、网站优化、网站认证、特克斯ssl等。为上千企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的特克斯网站制作公司
如果文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额随意,重在心意^_^
我要捐赠: 点击捐赠
Cocos2d-X×××:点我传送
提供给Objective-C程序员的基本内存管理模型有以下三种:
1)自动垃圾收集。(iOS运行环境并不支持垃圾收集,在这个平台开发程序时没有这方面的选项,只能用在Mac OS X 程序上开发。这个机制挺恶心的,用mac电脑的人知道,当内存不足的时候,机器基本上就是卡死了。)
2)手工引用计数和自动释放池。(这种方式,对程序员的要求很高。自己维护嘛,)
3)自动引用计数(ARC)。
retain和release方法:
当对象的引用计数为0的时候, 系统就知道不再需要这个对象了, 就会释放它内存。
一个对象的创建可以通过alloc分配内存或copy复制,
release会使引用计数减1 。
#import实现如下:@interface Song : NSObject { NSString *title; NSString *artist; long int duration; } //操作方法 - (void)start; - (void)stop; - (void)seek:(long int)time; //访问成员变量方法 @property NSString *title; @property NSString *artist; @property(readwrite) long int duration; //构造函数 -(Song*) initWithTitle: (NSString *) title andArtist: (NSString *) artist andDuration:( long int )duration ; @end
#import "Song.h" @implementation Song @synthesize title; @synthesize artist; @synthesize duration; //构造函数 -(Song*) initWithTitle: (NSString *) newTitle andArtist: (NSString *) newArtist andDuration:(long int)newDuration { self = [super init]; if ( self ) { self.title = newTitle; self.artist = newArtist; self.duration = newDuration; } return self; } - (void)start { //开始播放 } - (void)stop { //停止播放 } - (void)seek:(long int)time { //跳过时间 } -(void) dealloc { NSLog(@"释放Song对象..."); [title release]; [artist release]; [super dealloc]; } @end
#import#import "Song.h" int main (int argc, const char * argv[]) { Song *song1 = [[Song alloc] initWithTitle:@"Big Big World" andArtist:@"奥斯卡.艾美莉亚" andDuration:180]; Song *song2 = [[Song alloc] initWithTitle:@"It's ok" andArtist:@"atomic kitten" andDuration:280]; // print current counts NSLog(@"song 1 retain count: %i", [song1 retainCount] ); NSLog(@"song 2 retain count: %i", [song2 retainCount] ); // increment them [song1 retain]; // 2 [song1 retain]; // 3 [song2 retain]; // 2 // print current counts NSLog(@"song 1 retain count: %i", [song1 retainCount] ); NSLog(@"song 2 retain count: %i", [song2 retainCount] ); // decrement [song1 release]; // 2 [song2 release]; // 1 // print current counts NSLog(@"song 1 retain count: %i", [song1 retainCount] ); NSLog(@"song 2 retain count: %i", [song2 retainCount] ); // release them until they dealloc themselves [song1 release]; // 1 [song1 release]; // 0 [song2 release]; // 0 return 0; }
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; … … [pool release];// [pool drain];
#importint main (int argc, const char * argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSArray *weeksNames1 = [NSArray arrayWithObjects: @"星期一",@"星期二",@"星期三",@"星期四" ,@"星期五",@"星期六",@"星期日",nil]; NSArray *weeksNames2 = [[NSArray alloc] initWithObjects: @"星期一",@"星期二",@"星期三",@"星期四" ,@"星期五",@"星期六",@"星期日",nil]; //[weeksNames1 release]; //[weeksNames1 autorelease]; //[weeksNames2 release]; //[weeksNames2 autorelease]; NSLog(@" retain count: %i" , [weeksNames1 retainCount] ); NSLog(@" retain count: %i" , [weeksNames2 retainCount] ); [pool release]; return 0; }
Foundation框架中对象的创建有两类方法:
类级构造方法不能使用 release, 可以不用 autorelease就可以自动纳入内存释放池管理。
实例构造方法, 如果发出release消息就马上释放对象,
在iOS开发中由于内存相对少, 因此基本上都采用实例构造方法实例化对象,
在Song类中给成员变量设置方法如下:
- (void) setTitle:(NSString *) newTitle { title = newTitle; } - (void) setArtist:(NSString *) newArtist { artist = newArtist; }
- (void) setTitle:(NSString *) newTitle { [newTitle retain]; [title release]; title = [[NSString alloc] initWithString: newTitle]; } - (void) setArtist:(NSString *) newArtist { [newArtist retain]; [artist release]; artist = [[NSString alloc] initWithString: newArtist]; }
- (void) setDuration:(long int) newDuration { duration = newDuration; }此外, 在构造方法中也必须要注意, 不能直接赋值title =newTitle, 而是要调用自身的设置方法:
//构造函数 -(Song*) initWithTitle: (NSString *) newTitle andArtist: (NSString *) newArtist andDuration:(long int)newDuration { self = [super init]; if ( self ) { [self setTitle:newTitle]; [self setArtist:newArtist]; [self setDuration:newDuration]; } return self; }
- (void) setTitle:(NSString *) newTitle { title = newTitle; }
(void) setTitle:(NSString *) newTitle { [newTitle retain]; [title release]; title = [[NSString alloc] initWithString: newTitle]; }
- (void) setTitle:(NSString *) newTitle { [newTitle copy]; [title release]; title = [[NSString alloc] initWithString: newTitle]; }
手工内存管理规则的总结:
1)如果需要保持一个对象不被销毁,可以使用retain。在使用完对象后,需要使用release进行释放。
2)给对象发送release消息并不会必须销毁这个对象,只有当这个对象的引用计数减至0时,对象才会被销毁。然后系统会发送dealloc消息给这个对象用于释放它的内存。
3)对使用了retain或者copy、mutableCopy、alloc或new方法的任何对象,以及具有retain和copy特性的属性进行释放,需要覆盖dealloc方法,使得在对象被释放的时候能够释放这些实例变量。
4)在自动释放池被清空时,也会为自动释放的对象做些事情。系统每次都会在自动释放池被释放时发送release消息给池中的每个对象。如果池中的对象引用计数降为0,系统会发送dealloc消息销毁这个对象。
5)如果在方法中不再需要用到这个对象,但需要将其返回,可以给这个对象发送autorelease消息用以标记这个对象延迟释放。autorelease消息并不会影响到对象的引用计数。
6)当应用终止时,内存中的所有对象都会被释放,不论它们是否在自动释放池中。
7)当开发Cocoa或者iOS应用程序时,随着应用程序的运行,自动释放池会被创建和清空(每次的事件都会发生)。在这种情况下,如果要使自动释放池被清空后自动释放的对象还能够存在,对象需要使用retain方法,只要这些对象的引用计数大于发送autorelease消息的数量,就能够在池清理后生存下来。
自动引用计数(ARC):
强变量,通常,所有对象的指针变量都是强变量。
如果想声明强变量,可以使用__strong Faction *fl;这样的__strong来修饰。
值得注意的是,属性默认不是strong,其默认的特性是unsafe_unretained类似assign。
所以需要声明属性strong时,可以如下:
@property (strong, nonatomic) NSMutableArray *birdNames;
编译器会保证在事件循环中通过对赋值执行保持操作强属性能够存活下来。
带有unsafe_unretained(相当于assign)或weak的属性不会执行这些操作。
弱变量,可以使用__week关键字来声明。弱变量不能阻止引用的对象被销毁。
当引用的对象释放时,弱变量会被自动设置为nil。
需要注意的是,在iOS4和Mac OS V10.6中不支持弱变量。
在这种情况下,你仍然可以为属性使用unsafe_unretained, assing特性.
ARC都会在“底层”发生,所以一般不用关心。
当前文章:Objective-C之成魔之路【17-内存管理】
文章路径:http://myzitong.com/article/jhppho.html