码迷,mamicode.com
首页 > 移动开发 > 详细

iOS开发入门 ? OC语言·笔记五

时间:2017-02-22 12:46:20      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:self   fan   ros   setter   5.5   计数器   table   com   释放   

MRC 手动管理内存

1.1 内存引用平衡原则

1) 如果使用alloc,new开头,或者是copy(复制一个对象)来创建一个对象,意味着你拥有这个对象的所有权。这个对象的引用计数器初始值为1(也有可能>1)

2) 如果你拥有这个对象的所有权,在不使用此对象时,就有责任向对象发送release消息。(谁创建了对象,谁就有责任release这个对象)

3) 如果并不拥有一个对象的所有权,而想要使用这个对象,为了防止你在使用此对象期间,对象被别人释放掉,需要向对象发送retain消息,以保持对象。此时可以认为,你也拥有了这个对象所有权。

4) 当你使用完retain过的对象后,有责任release一下这个对象。

(谁retain了一个对象,谁就有责任release这个对象)

 

       配对出现:(+1、-1 ==>平衡) 

我们创建的对象不用了,就release;我们retain的对象不用了,就release

 

    内存管理的原则就是有加就有减。也就是说, 一次allocnew对应一次release, 一次retain对应一次release

1.2 自动释放池(autoreleasepool)

通过自动释放池来管理对象,只需要一个自动释放池,可以管理很多对象,当自动释放池结束的时候,会自动向池中的每个对象都发送release消息。

1) 如果一个对象创建后,不能马上释放它,但又不得不尽到释放对象的责任,此时可以将对象放入自动释放池,延迟对象的释放时机。比如绝大部分工厂方法都是如此。工厂方法中的对象是方法中创建的,按理来说应该由工厂方法内部释放,但工厂方法的功能决定了这个对象不能马上释放,此时应该将对象放入自动释放池。

2) 当自动释放池结束时,会向池中的所有对象发送release消息,如果此时,池中的对象的引用计数器是1,那么,对象会被释放掉。

3) 如何开始和结束一个自动释放池呢?

//自动释放池,用于回收对象的存储空间。

@autoreleasepool{ //开始创建一个自动释放池

  ……  ……

} //结束自动释放池销毁了, 给自动释放池中所有的对象发送一条release消息

      还有一种性能低下,被淘汰的自动释放池创建方式(了解)

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];//开始一个自动释放池

   ……  ……

[pool drain];//结束一个自动释放池

4) 无论一个对象是否在自动释放池,只要这个对象是由别人创建的,你要使用此对象,就得retain,用完此对象,就得release,即使对象在自动释放池,也依然如此。

5) 实际开发中,合理使用自动释放池来避免内存使用出现峰值。

如果App出现的内存使用的峰值,此时才考虑是否是由于大量使用工厂方法造成的,是否需要使用自动释放池解决问题。要合理使用自动释放池,大量使用会消耗系统资源。

 

6) autorelease方法:在自动释放池中使用,目的是将对象添加到自动释放池中。自动释放池销毁时会对池中对象作release操作。(延迟release)

 

@autoreleasepool {

Person *p = [[[Person alloc] init] autorelease];

        

}

  • autorelease方法与release方法的区别:这两个方法都能把对象的引用计数器减1。
    • release是一个精确的减1,对对象的操作只能在release之前进行,如果是在之后,就会出现野指针错误;
    • autorelease是一个不精确的引用计数器减1,当给对象发送autorelease消息时,对象就会被放到自动释放池中,自动释放池销毁时会给池中的所有对象发送release消息,使得所有对象的计数器减1,所以本质上autorelease还是会调用release。
  • 常见错误:

// 销毁自动释放池的时候 要对person再执行release操作的话 会报野指针错误

@autoreleasepool {

Person *person = [[[Person alloc] init] autorelease];

[person release];

// 对象执行两次autorelease意味着自动释放池销毁的时候 对象会执行两次release操作 会报野指针错误

@autoreleasepool {

Person *person = [[[[Person alloc] init] autorelease] autorelease];

1.3 setter方法的内存管理(应用场景:两个类是聚合关系)

当一个方法传入一个对象后,如果需要将这个对象用实例变量等手段保存起来持续使用时,需要做以下事:

1) 先将此对象的引用计数器加1(retain)

2) 再将原来实例变量指向的对象的引用计数器减1(release)

3) 最后将传入的对象地址保存到实例变量中

4) retain的对象通常需要在dealloc方法中release.

 

只要一个对象想使用房间,就需要对这个房间的引用计数器+1

只要一个对象不想使用房间,就需要对这个房间的引用技术器-1

      技术分享

经常会被问到的问题:

1) 前面3个顺序可否颠倒?

能不能先release原来的对象,再赋值,最后retain新对象? 一般可以,但不建议

       技术分享

2) dealloc方法中,可不可以使用self.属性 = nil;的方式释放属性所指向的对象? ok

可以的,self.属性 相当于调用上面的setter方法(该方法中有向对象发release

    Demo:setter方法的内存管理

     技术分享

    技术分享

 

iOS开发入门 ? OC语言·笔记五

标签:self   fan   ros   setter   5.5   计数器   table   com   释放   

原文地址:http://www.cnblogs.com/bossren/p/6428254.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!