iOS内存管理 -讲的不错,角度独特

ios的内存管理,包括对象的所有权与引用计数、自动释放、访问器方法与属性、一些会改变引用计数的特殊情况   
       ----- 对象所有权(ownership) 与引用计数 (retain count 、reference count)

       当一个所有者(owner,其本身可以是任何一个Objective-C对象)做了以下某个动作时,它拥有对一个对象的所有权(ownership)
       1、创建一个对象,包括使用任何名称中包含 "alloc"   "new"  "copy"的方法
       2、保留(retain)一个对象
       一个对象可以有多个所有者,一个所有者也可以拥有多个对象

      相应的,引用计数增减的基本规则是:
       1、当所有者创建一个对象时,该对象的引用计数为1
       2、当所有者保留它时,该对象的引用计数加1
       3、当所有者释放(release)它时,该对象的引用计数减1
       当一个所有者对于一个对象的引用计数的增减总计为0时,它放弃了对这个对象的所有权

      从两个不同的角度来看内存问题。
       1、当一个对象有着至少一个所有者(owner)的时候,它依然存在;当它没有任何所有者的时候,它会被释放掉
       2、从引用计数的角度看,一个对象存在时,其引用计数大于0,当一个对象的引用计数为0时,它会调用dealloc方法并释放掉
       两者的关系是:在所有权的背后起作用的机制是引用计数机制。我们只应当使用所有权的概念来管理内存,因为如果试图直接获取对象的引用计数,那么得到的数字会匪夷所思 -- 系统的一些框架会“偷偷”增减对象的引用计数

      内存管理的目标:
      当一个对象的某个所有者依然需要使用它时,保证这个对象的存在;当一个对象的所有者不再需要它时,保证这个对象被销毁。因此只要任何一个所有者在使用完一个对象之后释放掉它,那么内存管理的目标就可以实现。
      任何一个所有者(所有者本身也只是一个对象)所应当遵守的基本步骤:拥有一个对象 -> 使用一个对象  -> 放弃对象的所有权
      从引用计数的角度来看:还需要这个对象时,保持对其增减为正;不再需要这个对象时,保持对其增减为0

      下图,所有者1和所有者2单独地执行了拥有对象、使用对象、放弃对象所有权的步骤;当所有者1不再需要该对象时及时放弃了所有权,但此时所有者2依然拥有该对象,因此该对象依然存在,所有者2可以继续使用它;当2也不再需要该对象时,也放弃掉所有权;这时对象不再有任何所有者,因此立刻被销毁掉
     所有者2只是复制了该对象的指针,并没有使用copy方法,因此复制指针这个操作本身并不增加对象的引用计数;因为所有者2希望能使用该对象,因此通过retain方法成为它的所有者,也保证了所有者1放弃该对象时,对象不被销毁。

     
   右手边前两个步骤的代码实现应该为   if(obj1 != obj){ [obj1 release];   obj1 = [obj retain]; }

 
       有时候一个所有者创建一个对象后,会立刻将该对象的指针传递给其他所有者,这时,这个创建者不希望再拥有这个对象,如果立刻给它一个release,会导致这个对象被立刻被释放掉,这样其他所有者还没来得及保留该对象,解决这个问题的方法是,给对象发送一个autorelease消息:这样创建者不再拥有该对象的所有权:该对象成为自动释放的对象,但不会立刻被释放掉,其他所有者可以有时间保留或者赋值该对象,并成为其唯一所有者。
      看一个自动释放的demo,一所有者先用alloc方法创建一个对象,此时该所有者拥有了这个对象,对象的引用计数为1.接着,所有者自动释放该对象,所有者此时已经放弃了所有权,但对象的引用计数在一段时间内依然为1. 此时可以看出自动释放的另一个好处,不会因为忘记给对象发送release 而造成内存泄露。
       -(Object *)returnAutoreleaeObject{
       object *obj = [object alloc]init];
       return [obj autorelease];
       }
    与自动释放相关的,有一大类构造方法,由它们构造的对象直接就是自动释放的对象,这一类哦鼓噪方法叫便捷方法,比如stringWithFormat , NSArray 的arrayWithObjects:和 arrayWithArray:,UIImage的imageNamed:,NSNumber的numberWithBool等,autoreleae方法会在一段时间以后释放掉一个对象,在这段时间内我们可以安全地使用该对象,这段时间是多久呢?
     先看看自动释放池,其是NSAutoreleasePool的实例,包含了收到autorelease消息的对象,当一个自动释放池自身被销毁(dealloc)时,它会给池中每一个对象发送一个realeae消息,一个自动释放的对象,至少能够存活到自动释放池销毁的时候。
      自动释放池在每一个时间周期(event cycle)的开始,系统会子弟哦那个创建一个,在每一个事件周期的末尾,系统会自动销毁。可这样理解:当代码在持续运行时,自动释放池是不会被销毁的,此时可以安全的使用自动释放的对象,当代码运行告一段落,开始等待用户输入或者其他事件时,自动释放池就被自动释放掉,池中的对象都会收到一个release消息。
      自动释放而非直接释放,可以帮助节省一些代码量,提供开发速度,但有一个直接的缺点:延缓了对象的释放,在有大量自动释放对象的时候,会占用大量内存资源,因此,需要避免大量对象自动释放。
      在以下情况,需要手动建立并手动销毁自动释放池:
      1、当在主线程外开启其他线程时:系统只会在主线程自动生成并销毁掉自动释放池
      2、挡在短时间内制造了大量自动释放对象时:及时地销毁有助于有效利用手机上的内存资源

 

转:http://qk13warcraft.blog.163.com/blog/static/15754934420129213170934/

 

 

 

posted @ 2014-04-23 23:50  ygm900  阅读(405)  评论(0编辑  收藏  举报