• objc内存管理


    http://blog.sina.com.cn/s/blog_538ee4a70100o9o2.html

    如果要从事Leopard或更高版本的MacOS程序开发使用Objective-C 2.0的垃圾回收机制,若要从事旧版本MacOSiPhone开发则要全部阅读本章内容

    一、对象生命周期

    程序中的对象由生命周期,其周期包括:诞生(allocnew)、生存(接受消息和执行操作)、                                                                               交友(借助方法的组合和参数)和消亡(被释放)

     

    1、引用计数

    Cocoa采用了一种称为引用计数(保留计数)的技术:

    (1)每个对象有一个与之相关联的整数,称为他的引用计数器或保留计数器

    (2)当代码访问某个对象时,改代码将该对象保留计数器值增加1,表示我要访问该对象

    (3)当代码结束对象访问时,将对象的保留计数器值减1,表示不再访问该对象

    (4)在保留计数器值为0时,表示不再有代码访问该对象,对象将被销毁,启动垃圾回收机制

     

    使用方法:

    (1)使用allocnew或通过copy消息(生成接收对象副本)创建对象时对象的保留计数器数值被设置为1

    (2)要增加计数器值,可以调用对象的retain方法

    -(id) retain; 返回一个id类型值。

    通过这种方式,可以嵌套执行带有其他方法参数的保留调用,增加对象的保留计数器值并要求对象完成某种操作

    例:[[car retain] setTire : tire anIndex : 2]    

    表示要求car对象将其保留计数器值加1并执行setTire操作

     

    (3)要减少对象的保留计数器值,调用对象的release方法

    -(void) release;

    (4)当对象因保留计数器归0将被销毁时,Objective-C自动调用dealloc方法,此方法可重写,但不要直接调用,而是要让Objective-C自动调用

    -(unsigned) retainCount;

    (5)获得当前保留计数器的当前值,可以调用retainCount方法

     

    2、对象所有权object ownership

    如果一个对象具有指向其他对象的实际变量,则称该对象拥有这些对象

     

    3、访问方法中对象的保留和释放

    -(void) setEngine : (Engine *) newEngine

    {

             [newEngine  retain];//增加newEngine的保留计数器

             [engine  release];//减少engine的保留计数器

             engine = newEngine;//engine保存为newEngine

    }

    二、自动释放

    1、所有对象全部入池

    Cocoa中有一个自动释放池(autorelease  pool),他是一个存放实体的池(集合),这些实体可能是对象,能被自动释放

    NSObject类提供了一个autorelease方法:-(id) autorelease;

    该方法预先设定了一条在将来某个时间发送的release方法,其返回值是接收消息的对象

    当给一个对象发送autorelease方法时,实际上是将该对象添加到NSAutoreleasePool中,自动释放池被销毁时,回想该池中的所有对象发送release消息

    举例代码:

             -(NSString  *)description

             {

                       NSString  *description;

                       description = [[NSString alloc] initWithFormat : @"I am %d years old",4];

                       return ([desciption autorelease]);

             }

    description方法首先创建了一个新的字符串对象,然后自动释放,最后将其返回给调用的函数

     

    2、自动释放池的销毁时间

    Cocoa定期自动创建和销毁自动释放池,通常是在处理完当前事件以后执行操作。

    我们可以使用任意多的自动释放对象,当不需要他们时,自动释放池将自动为你清理这些对象

    NSAutoreleasePool  *pool;

    pool = [[NSAutoreleasePool alloc] init];

    ……

    [pool release];

    TipXcode自动生成的另一种销毁自动释放池-drain方法只是清空自动释放池而不销毁它,这种方法只适用于10.4以及更高版本,使用-release方法适用于全部版本

     

    3、自动释放池的工作过程

    举例代码:

             int main(int argc, const char *argv[])

             {

                       NSAutoreleasePool *pool;                          //首先创建一个自动释放池

                       pool = [[NSAutoreleasePool alloc] init];

     

                       RetainTracker *tracker;                              //新的tracker对象被创建

                       tracker = [RetainTracker new];                 //保留计数器值为1

     

                       [tracker retain];                                             //使保留计数器值增加到2

                       [tracker autorelease];                                 //将对象添加到自动释放池,值仍为2

                       [tracker release];                                          //释放对象,保留计数器值为1,对象仍存在

     

                       NSLog(@"releasing pool");

                       [pool release]; //销毁自动释放池,NSAutoreleasePool是一个普通对象遵从相同的内                                                存管理规则,因为创建时发送了alloc消息其保留计数器为1,执行                                                        release后变为0,自动释放池将被销毁

                       return(0);                   //函数返回0表示全部操作成功执行

             }

     

    三、Cocaoa内存管理规则

    规则:

    (1)    当使用newalloccopy方法创建一个对象时,该对象的保留计数器值为1

             当不再使用该对象时,向该对象发送releaseautorelease消息,该对象将被销毁

    (2)    当对象被设置为自动释放,我们不需要执行任何操作来确保该对象被清理

             如果要在一段时间内拥有该对象,则需要保留它并确保操作完成时释放他

    (3)    如果保留了某个对象,需要释放或自动释放该对象,需保持retainrelease方法的使   用次数相等

     

    1、临时对象

    使用任何其他方法(非newalloc或者copy)获得对象不需要关心如何销毁该对象

    举例代码:

             NSMutableArray  *array;

             array = [NSMutableArray arrayWithCapacity : 17];

    arrayWithCapacity不属于allocnewcopy方法,使用该方法返回的对象保留计数器值为1并且已经被设置为自动施放

    举例代码:

             NSColor *color;

             color = [NSColor blueColor];

    blueColor返回一个全局单例对象,这个对象永远不会被销毁

     

    2、拥有对象

    (1)使用newalloccopy方法获得对象,手动释放

    举例代码:

             -(void) doStuff

             {

                       flonkArray = [NSMutableArray new];

             }

             -(void) dealloc

             {

                       [flonkArray release];

                       [super dealloc];

             }

    (2)使用非newalloccopy方法获得对象,自动释放

             -(void) doStuff

             {

                       flonkArray = [NSMutableArray new];

                       [flonkArray retain];           //唯一的不同点

             }

             -(void) dealloc

             {

                       [flonkArray release];

                       [super dealloc];

             }

     

    (3)再循环中清空自动释放池

    举例代码:

             NSAutoreleasePool *pool;

             pool = [[NSAutorelease alloc] init];

             int i;

             for(i = 0; i < 1000000; i++){

                       id object = [someArray  objectAtIndex : 1];

                       NSString  *desc = [object description];

                       if(i % 1000 == 0){                         //每循环1000次时清理一次自动释放池,如果不这样                                [pool release];                    //做将会在1百万次循环时清理内存,程序将非常慢

                                pool = [[NSAutorelease alloc] init];

                       }

             }

             [pool release];

     

    3、垃圾回收

    Objective-C 2.0引入了自动内存管理机制,也称垃圾回收

     

    启动垃圾回收功能:转到项目信息窗口的Build选项卡,然后选择Required [-fobjc-gc-only]选项即可

    Tip: -fobjc-gc是为了使代码既支持垃圾回收又支持对象的保留和释放

     

    启用垃圾回收以后,内存管理命令全部变成了空操作指令,不执行任何操作

     

  • 相关阅读:
    update condition 字段报错
    Xshell连接Linux服务器总掉线
    sleep php函数
    ubuntu 16.04 镜像下载
    多线程Parallel和Task
    AngularJS 时间格式化
    正则表达式
    手机抓包
    内存泄漏
    字符集编码和排列规则
  • 原文地址:https://www.cnblogs.com/ligun123/p/2152303.html
Copyright © 2020-2023  润新知