zoukankan      html  css  js  c++  java
  • ios内存管理

    部分内容摘自《Objective-C基础教程》和互联网

    引用计数

           Cocoa采用了引用计数(reference counting)机制,每一个对象有一个关联的“整数retainCount”用于记录对象的使用情况。对象被引用时retaincount+1,外部环境结束对象的使用后retainCount-1.当retaincount为0的时候,该对象被销毁。

            当我们使用alloc、new或者copy的我们需要销毁这个对象。release函数,只是将对象的retainCount值减1,并不是删除对象。当retainCount==0的时候,系统会发给对象一个dealloc消息, 另外:千万不要手动调用dealloc,因为我们不知道何时,何地,何人还会使用该对象 。应该老老实实依赖引用计数机制完成内存管理。

            释放对象所有权的函数除了release还有autorelease,这是一种延迟操作,下面会详细介绍。

            当我们看到下面代码,

        第一个问题 :dateformatter 的内存管理,应该很好理解,因为 [NSDateFormatter   alloc ] 所以,我们要release它。

    -(NSString*) date2String:(NSString*)str

    {

        NSString* dateString;

        NSDate *  currentTime=[NSDate date];

        NSDateFormatter   *dateformatter=[[ NSDateFormatter alloc ] init ];

        [dateformatter setDateFormat:str];

        dateString =[dateformatter stringFromDate:currentTime];

        [dateformatter release ];

        return dateString;

    }

    那么,这个函数中的 NSString * dateString  NSDate  *  currentTime 这两个变量,在怎样进行内存管理。还有,局部 dateString 作为返回值,内存管理又是如何?这是个好问题。

            我们发现dateString的赋值方法是 [ dateformatter stringFromDate:current ] ,显然,它并没有使用alloc、new或copy任何一种。《Objective-C基础教程》上说:假设dateString对象被返回时保留引用计数值为1。呵呵,“假设”俩字。这本书还真是基础教程!

            刚才《Objective-C基础教程》说过,OC里没有栈上对象,没有临时对象。那么这个dateString算是什么?

            那么,现在将他们放到自动释放的范畴,可以这么理解:[ dateformatter stringFromDate:current ] 里面alloc新的对象。这个对象就是autorelease的。

           下面将详细介绍自动释放。

    自动释放池autoreleasepool

            自动释放池是NSAutoreleasePool的实例,其中包含了收到autorelease消息的对象。当一个自动释放池自身被销毁(dealloc)时,它会给池中每一个对象发送一个release消息(如果你给一个对象多次发送autorelease消息,那么当自动释放池销毁时,这个对象也会收到同样数目的release消息)。可以看出,一个自动释放的对象,它至少能够存活到 自动释放池销毁 的时候。 

            

            简单的说一个例子,返回局部堆上变量的指针(用c++的口吻说的),那么这个对象如何释放?Objective-C发明了自动释放机制。

    -(obj*) foo

    {

    obj* temp = [[obj alloc]init];

    return [ obj autorelease ];//只是在返回的时候加上关键字autorelease

    }

    《Objective-C基础教程》上说:自动释放(autorelease)是一种延迟释放机制,这样保证局部堆上的变量能够被外部正常使用。

    但是,系统又是什么时候释放的呢? 在每一个事件周期( event cycle )的开始,系统会自动创建一个自动释放池;

            在每一个事件周期的结尾,系统会自动销毁这个自动释放池。一般情况下,你可以理解为:当你的代码在持续运行时,自动释放池是不会被销毁的,这段时间内你也可以安全地使用自动释放的对象;当你的代码运行告一段落,开始等待用户输入(或者其它事件)时,自动释放池就会被释放掉,池中的对象都会收到一个 release 消息,有的可能会因此被销毁。

            这是很难确定的时间,如果自动释放池的销毁时间过早,那么程序就很危险,这个恐怕很难满足程序员的要求吧。

            自动释放池的缺点:它延缓了对象的释放,在有大量自动释放的对象时,会占用大量内存资源。因此,你需要避免将大量对象自动释放。并且,在以下两种情况下,你需要手动建立并手动销毁掉自动释放池:

    1.当你在主线程外开启其它线程时:系统只会在主线程中自动生成并销毁掉自动释放池。

    2.当你在短时间内制造了大量自动释放对象时:及时地销毁有助于有效利用iPad上有限地内存资源。

         所以,本人不建议使用autorelease的机制,如果遇到上面例子的情况,使用典型的解决方法吧,外部一个对象负责删除obj对象,防止内存泄露。

    Convenience method的内存管理

            与自动释放相关的,有一大类构造方法(constructor method),由它们构造的对象直接就是自动释放的对象;这一类构造方法叫做便捷方法。比如下面这句的字符串就是一个自动释放的对象,stringWithFormat:就是一个便捷方法。

    NSString* string = [NSString stringWithFormat:@”autoreleaseString”];

    再举几个便捷方法的例子,方便读者以后的开发。

    1. NSArray  arrayWithObjects :和 arrayWithArray :。

    2. UIImage  imageNamed :。

    3. NSNumber  numberWithBool 等。

            也就是说这些方法返回的对象,我们可以用,但是还是不能确定得知道她什么时候dealloc,那么我们能不能主动删除这些“便捷函数”返回的对象呢?如果,程序中有大量的“便捷函数”,这样无疑占用了大量内存空间。

            难道只能避免循环调用这种“便捷函数”?

            现在我们已经解释了,autorelease方法会在一段时间以后释放掉一个对象,在这段时间内我们可以安全地使用该对象。那么这段时间究竟是多久呢?

            上面已经介绍了自动释放的机制,“便捷函数”产生的对象至少能够存活到 自动释放池销毁 的时候。

    ARC(自动引用计数Auto Reference counting)

            上面的文字介绍了“引用计数”这里又来个更高级的自动引用计数。

    请参考这篇文章 http://blog.csdn.net/zkdemon/article/details/7446385 

    /****************************************下面说以下典型的应用****************************?

    self.xxx的作用。

         NSInteger i = 0 ;

    第一行     _extraMessage = [[ FtExportMessage alloc ] init ];

    第二行    //self . extraMessage  = [[ FtExportMessage   alloc ] init ];

        i = [ self . extraMessage retainCount ];

        [ self . extraMessage release ];

    你会发现:运行第一行时,retainCount是1,这个好理解。但是不要使用第二行代码,retaincount是2,及时这个时候你调用release也不会删除对象。

    初学者容易犯错,什么地方都用self.XXX.

    NSArray和NSDictionary的添加元素,内存管理

    这种集合类,只是让“元素”的retainCount加1.同样,当NSDictionary release的时候,会将“元素”

    - ( void )prepareData

    {

         _buddyMsg   = [[ ExportMsgEntity alloc ] init ];

        _pgMsg      = [[ExportMsgEntity alloc] init];;

        _dgMsg      = [[ExportMsgEntity alloc] init];

        _msgGroup = [[ NSMutableDictionary alloc ] initWithObjectsAndKeys :

                         self . buddyMsg , KMsgBuddy ,

                         self.pgMsg,KMsgPGGroup,

                         self.dgMsg,KMsgDGGroup,nil ];

        int i= 0 ;

        i = self . buddyMsg . retainCount ;//此时 i=2

    }

    上面的代码使 self . buddyMsg 的retainCount从1加1成为2.那么,当NSDictionary析构后呢,请看下面的情况 

    - ( void )deleteDictionary

    {

        [ self . msgGroup release ];

        int i= 0 ;

        i = self . buddyMsg . retainCount ;//此时 i=1

    }

    上面代码使得 self . buddyMsg 的retainCount从2减1成为1

    总结:使用这些“集合”的时候,不要妄想着“集合”release的时候会自动删除里面的元素。最后还是元素自己release资源。

  • 相关阅读:
    开博了,将会定期更新博客
    C++实验二
    C++实验三
    c++第八章课后题
    c++第八章复数运算
    我的第一篇Window Live Writer日志
    Item 3: Prefer the is or as Operators to Casts(选择is或者as操作符而不是做强制类型转换)
    C# 中list的排序
    CodeSmith的应用
    using 关键字
  • 原文地址:https://www.cnblogs.com/yulang314/p/3551540.html
Copyright © 2011-2022 走看看