zoukankan      html  css  js  c++  java
  • IOS开发小记-内存管理

        关于IOS开发的内存管理的文章已经很多了,因此系统的知识点就不写了,这里我写点平时工作遇到的疑问以及解答做个总结吧,相信也会有人遇到相同的疑问呢,欢迎学习IOS的朋友请加ios技术交流群:190956763,共同学习,共同进步!

        假如在.h文件里,定义一个变量@property (nonatomic,retain) AController  *aController;

        疑问1:创建对象时候,一般会使用alloc,new,copy或者mutalbeCopy等方法,

        哪种写法是正确的?

        A self.aController=[[AController alloc] init];

        B self.aController=[[[AController alloc] init] retain];

        C self.aController=[[[AController alloc] init] autorelease];

        D self->aController=[[AController alloc] init];

        答案:C,D   引用计数的主要接口alloc,allocwithzone,new(带初始化) 为对象分配内存,retainCount为“1”,并返回此实例,而调用self.aController,self本身有干了活,他把_aController这个变量相当于又retain一下,因此A的retaincount已经是2了,已经泄露了!因此不需要B这样retain了,加autorelease的话,就会把刚才新建那块内存自动释放掉的,如果用D话,没有执行aController的setter方法,因为此时retainCount为“1”,所以D也是正确的,C的话也能用,但是不是好的用法

        疑问2:在dealloc方法中,这么写有问题吗?

    - (void)dealloc{
        [self.aController release];
        self.aController = nil;
        [super dealloc];
    }

        答案:这里不需要release了,因为self.aController = nil;已经调用了release了,当然也可以这么写

    - (void)dealloc{
        [self->aController release];
        self->aController = nil;
        [super dealloc];
    }

    解释:对于set method来说,用synthesize来让系统帮我们生成的set方法和如下的类似:

    - (void)setAbc:(id)newAbc
    {
          if(_abc != newAbc){
               [_abc release];
               _abc = [newAbc retain]; //是retain还是copy取决于你property声明时的attributes  
           }
    }

    如果新值和成员相等,就不需要进行重复的赋值了,不等的话,需要把新值赋给成员,同时,成员_abc原来的内容就不需要了,这里要先调用release进行释放。(这个具体的原因在那本讲Objective-C的书中写的很清楚,请查看)。

    因此在这里,调用self.abc = nil;
    就等于已经调用了[_abc release];  和_abc = nil;

    self.abc = nil;和[_abc release]; 都不一定释放对象,因为该对象还可能被别的引用,这里的操作的意图就是:别的地方用没用_abc我不知道,在这里的_abc我不用了。

    为什么release后还要设置nil呢?因为是这样的,如果引用 计数等于0还对该对象进行操作,则会出现内存访问失败,crash,所以尽量设置为nil,但是单纯设置为nil,如果retaincount不是0的话,内存一样泄露的,因此应该设置nil的时候,先保证变量的retaincount是0了

    疑问3:为什么有些变量不用考虑retain,release呢?

    NSString *str1 = @”constant string”;

    str1retain count是个很大的数字。Objective-C对常量字符串做了特殊处理。

    当然,如果你这样创建NSString,得到的retain count依然为1

    NSString *str2 = [NSString stringWithFormat:@”123”];

    实际上对于 [NSString stringWithFormat:] 这类构造函数返回的对象都是autorelease的,所以也不用考虑retain,release

    疑问4:在ARC的情况下,按说不用自己在考虑release了,为什么还会有dealloc方法存在呢?

    答案:虽然在ARC下,不用考虑release了,但是我们可能还要释放一些其他的东西,比如delegate,关闭定时器,关闭gps定位等,另外如果在ARC下,我们自己不放心,为了安全,自己释放变量也没有什么错误发生!另外不用再调用[super dealloc]了

    比如在ARC下,我们可能会这么写

    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
        [self.closeButtonTimer invalidate];
        [self.webView setDelegate:nil];
        [self setLocationDetectionEnabled:NO];
    }

    注意:比如Delegate,如果不在dealloc中释放它,如果页面有多线程的调用,比如开辟个线程从网上down图片子类的,它down下来后需要找这个页面,但是可能用户操作比较快,比如点了后退按钮,这时候页面可能已经销毁了,于是就导致页面崩溃了,所以dealloc中要释放掉delegate

    疑问5:怎么能知道哪里内存泄露了呢?

    这个就不详细解释了,看相关的帖子说的很详细了

    http://www.cocoachina.com/newbie/basic/2012/1204/5242.html

    疑问6:声明为IBOutlet属性的,在MRC中应该retain还是assign?在ARC中应该是strong还是weak?

     在MRC中,应该是retain的,因为IBOutlet本身就是retain的

    任何一个被声明为IBOutlet并且在Interface Builder里被连接到一个UI组件的成员变量,会被额外retain一次。
    常见的情形如

    IBOutlet UILabel *label;

    这个label在Interface Builder里被连接到一个UILabel。此时,这个label的retainCount为2。
    所以,只要使用了IBOutlet变量,一定需要在dealloc或者viewDidUnload里release这个变量。

    在ARC中,property,我们将其申明为weak(事实上,如果没有特别意外,除了最顶层的IBOutlet意外,自己写的outlet都应该是weak)。通过加载xib得到的用户界面,在其从xib文件加载时,就已经是view hierarchy的一部分了,而view hierarchy中的指向都是strong的。因此outlet所指向的UI对象不应当再被hold一次了。将这些outlet写为weak的最显而易见的好处是你就不用再viewDidUnload方法中再将这些outlet设为nil了(否则就算view被摧毁了,但是由于这些UI对象还在被outlet指针指向而无法释放)。

    参考:

    http://www.16kan.com/post/214006.html

    http://www.ityran.com/archives/1234

    疑问7:在ARC在,如果用retain,和用strong有什么区别?

    retain关键字在ARC中是依旧可用的,它在ARC中所扮演的角色和strong完全一样。为了避免迷惑,最好在需要的时候将其写为strong,那样更符合ARC的规则。

  • 相关阅读:
    hadoop中namenode发生故障的处理方法
    开启虚拟机所报的错误:VMware Workstation cannot connect to the virtual machine. Make sure you have rights to run the program, access all directories the program uses, and access all directories for temporary fil
    Hbase的安装与部署(集群版)
    分别用反射、编程接口的方式创建DataFrame
    用Mapreduce求共同好友
    SparkSteaming中直连与receiver两种方式的区别
    privot函数使用
    Ajax无刷新显示
    使用ScriptManager服务器控件前后台数据交互
    数据库知识
  • 原文地址:https://www.cnblogs.com/seesea125/p/3175431.html
Copyright © 2011-2022 走看看