IOS开发第三天-内存管理

来源:互联网 发布:莫知我哀 莫的意思 编辑:程序博客网 时间:2024/06/08 07:00

内存管理

对于有效的内存管理,通常认为包括两个方面的内容:

  1. 内存分配:当程序创建对象时需要为对象分配内存。应该采用合理的设计,劲量减少对象的创建,并减少对创建过程中的内存的开销。
  2. 内存回收:当程序不需要对象时,系统必须及时回收这些对象所占用的内存,以便程序可以再次使用这些内存。
在xcode4.2之前,OC的内存回收必须在程序中通过retain、release、autorelease方法去管理对象的引用计数,这样才能让程序正常回收内存,很容易造成内存泄漏;而在xcode4.2之后,引入了自动引用计数(Automatic Reference Counting,简称:ARC)。如果想使用ARC,那么在编译时使用-fobjc-arc选项来启动ARC机制,这样,ARC机制将会自动释放对象所占用的内存。

内存分配是非常简单的,重点在内存释放,对于开发Mac应用程序的程序员来说,OC提供了下面3种内存回收机制:

  1. 手动引用计数和自动释放池。
  2. 自动引用计数ARC
  3. 自动垃圾回收。
对于ios应用的开发读者而言,自动垃圾回收是无法使用的,IOS不支持自动垃圾回收。因此,对于IOS开发者而言,ARC是足够好的。下面从手动引用计数着手来说明。

对象的引用计数

OC采用引用计数来跟踪对象的状态,当一段代码需要访问某个对象时,该对象的引用计数+1;当这段代码不再访问该对象时,该对象的引用计数-1。当对象的引用计数为0时,表明程序不再需要该对象,系统回收该对象占用的内存。系统在销毁一个对象之前,会自动调用该对象的dealloc方法(该方法继承自NSObject)来执行一些回收的操作。通常调用被持有对象的release方法将引用计数-1。当对象被销毁之后(它的引用计数变为0,并且系统自动调用了该对象的dealloc方法),此时该对象已经不再存在;如果有一个指针此时指向这个被销毁的对象,那么称这个指针为悬空指针(Dangling Pointer),程序会出现未知错误。注意:程序员千万不能主动调用dealloc方法,当一个对象的引用计数为0时,系统会自动调用该对象的dealloc方法来将其销毁)。

改变对象的引用计数的方式如下:

  1. 当程序调用方法名以alloc、new、copy、mutabaleCopy开头的方法来创建对象时,该对象的引用计数+1;
  2. 程序调用对象的retain方法时,该对象的引用计数+1
  3. 程序调用对象的release方法时,该对象的引用计数-1;
NSObject提供了有关引用计数的方法如下:

  • -retain:将该对象的引用计数器+1;
  • -release:将该对象的引用计数-1;
  • -autorelease:不改变该对象的引用计数器的值,只是将该对象添加到自动释放池;
  • -retainCount:返回该对象的引用计数器的值。
retain方法返回调用该对象方法的对象本身,这样使对象在调用retain方法后可以直接再调用其他方法。需要注意的是,对于一些NSObject类中已有的方法,如果我们要重写,那么直接在@implementation实现这个函数即可,因为已经可以访问了。

当我们在程序中重写dealloc方法使,如下

-(void) dealloc{  //要回收的对象;    [super dealloc];}

在程序中一定要调用父类的dealloc方法,因为它的父类可能也有一些东西需要释放,执行[super dealloc]方法就是保证父类的dealloc方法被调用,从而保证父类对象所持有的东西得到释放。

案例代码如下:

LWBItem.h文件如下:

#import <Foundation/Foundation.h>@interface LWBItem:NSObject@end


LWBItem.m文件
#import"LWBItem.h"@implementation LWBItem-(id) init{    if(self=[super init]){        NSLog(@"init 方法中,引用计数为:%ld",[self retainCount]);    }    return self;}-(void)dealloc{    NSLog(@"系统开始销毁我了,再见");    [super dealloc];}@end

LWBUser.h文件如下:

#import <Foundation/Foundation.h>#import "LWBItem.h"@interface LWBUser:NSObject{LWBItem* _item;}@end
#import "LWBUser.h"@implementation LWBUser-(void) setItem:(LWBItem*)item{    if(_item!=item){        [item retain];        _item=item;    }}-(LWBItem*) item{    return _item;}-(void) dealloc{    [_item release];    [super dealloc];}@end
测试文件如下:

   LWBItem* item=[[LWBItem alloc] init];    LWBUser* user=[[LWBUser alloc]init];    [user setItem:item];    NSLog(@"the item count==%ld",[item retainCount]);    [item release];     NSLog(@"the item count==%ld",[item retainCount]);     NSLog(@"%@",[user item]);     [user release];

测试结果如下:

2017-04-12 20:08:18.765 LWBItem[8688] init 方法中,引用计数为2017-04-12 20:08:18.776 LWBItem[8688] the item count==22017-04-12 20:08:18.779 LWBItem[8688] the item count==12017-04-12 20:08:18.781 LWBItem[8688] <LWBItem: 0x6a79a8>2017-04-12 20:08:18.784 LWBItem[8688] 系统开始销毁我了,再见




0 0