zoukankan      html  css  js  c++  java
  • 初学者关于内存的思考(不断加深不断更新中)

    1、

    从最简单的说起,先看例子,看注释:

    -(void)fun1
    {
    str1 = @"我是str1";
    NSLog(@"str1的conut: %d",[str1 retainCount]);//-1 之所以为-1,是因为直接赋值后,"我是str1"被放在常量区,没有所谓引用
    }

    -(void) fun2
    {
    str2 = [NSString stringWithFormat:@"我是str2"];
    NSLog(@"str2的count: %d",[str2 retainCount]);//1。注意:stringWithFormat里面已经包含alloc和autorelease了
      //[str2 release];如果加了这句,程序就崩溃。因为已经包含了autorelese,下面fun4的str2就是非法引用
    }

    -(void) fun3
    {
    str3 = [[NSString alloc]init];
    str3 = @"我是str3";
    NSLog(@"str3的count: %d",[str3 retainCount]);//-1 alloc跟init被忽略了,效果如fun1
    }

    -(void) fun4
    {
    NSLog(@"str2:%@",str2);
    NSLog(@"str1:%@",str1);
      NSLog(@"str3:%@",str3);
    }

    在外面:
        NSLog(@"str2 final count:%d",[str2 retainCount]);//1 仍旧是1,因为由编译器来负责管理(autorelease)
        NSLog(@"str3 final count:%d",[str3 retainCount]);//-1

    由上面的代码示例可以看出直接赋值跟用*with*方法赋值的区别。

    stringWithFormat里面已经包含alloc和autorelease。确切地说,*with*方法都包含了alloc以及autorelease

    2、
    在声明为@property (nonatomic, retain) UIAlertView *alert时,这里的retain不是摆设,而是retain了一次,这就刚好跟dealloc对应,在dealloc里面release
    计数器加1了。所以在还没alloc之前,retainCount为1。
    在.h中声明alert为成员变量,并设为property的retain属性   

    UIAlertView *tmpAlert = [[UIAlertView alloc]initWithTitle:tempStr
    message:nil
    delegate:self
    cancelButtonTitle:@"取消"
    otherButtonTitles:@"确定",nil];
    self.alert = tmpAlert;
    [tmpAlert release];
    [alert addSubview:view];
    [alert show];
    在上例子中,一般就这么用,不要直接轻易去对alert进行alloc,这样很容易出错。常见的做法如上,设一个临时变量tmpAlert,赋值给alert后就release掉。注意,是赋值
    给self.alert,而不是alert。别忘了,self.alert = tmpAlert 这句话等价于[alert release];alert = [tmpAlert retain];(为什么?)所以,为了避免额外的
    错误,尽量在.h中声明property/retain属性,要赋值的时候就用self.***。


    3、成员变量跟property不一定要对应存在,没有成员变量只有property也是合法的,self.***访问的就是property。

    4、对一个尚未分配内存的变量进行release是合法的。但是一旦你alloc+init了之后,就不能那么随便release。请看下面比较:
        UIAlertView *alert = nil;
        [alert release];//正确
        
        UIAlertView *alert2 = [[UIAlertView alloc] init];
        [alert release];
        [alert release];//报错
        
        NSString *str = nil;
        [str release];//正确
        
        NSString *str2 = [[NSString alloc] init];
        [str2 release];
        [str2 release];//正确!!!!!

    可以看出,NSString类型是个特列,不管你有没有alloc分配内存给他,都可以随时release。

    从这个例子我们也可以看出,对于工程里面的成员变量,不应该随意去设@property属性,因为这样会暴露给别的类。但是这时候会有这样的烦恼,没有了(retain),似乎后面的内存管理会变得麻烦些。所以产生了另外一种方式,在.m文件里面,凡是用该成员变量(假设为A)的地方,首先要在init里面把A置为nil,这是为了后面release的方便,不会出错(对nil对象release是不出错的)。然后凡是对该变量进行赋值的地方,都要先release,赋值完后再retain,养成习惯吧,兄弟。

    5、@property、@synthesize

    这两个关键字是让成员变量生成相应的setter、getter。setter里面已经包含了必要的retain、release。平时我们用self.****就是访问setter,而没加self的就是访问普通的成员变量。

    看个例子:

     @interface Photo : NSObject

    {

    NSString* caption;

    NSString* photographer;

    }

    - (NSString*) caption;//getter 

    - (NSString*) photographer;

    - (void) setCaption: (NSString*)input;//setter,注意其默认的名字set+***

    - (void) setPhotographer: (NSString*)input;

    @end

    用@property实现简化如下:

    @interface Photo : NSObject

    {

    NSString* caption;

    NSString* photographer;

    }

    @property (retain) NSString* caption;

    @property (retain) NSString* photographer;

    @end

    这里的retain意思是,setter应该对input进行retain。
    http://cocoadevcentral.com/d/learn_objectivec/                    原链接

    - (void) dealloc

    {

    self.caption = nil;

    self.photographer = nil;

    [super dealloc];

    }

    6.下面介绍几个个人比较容易混淆的东西,非常实用!先总说一下,原则是:

    原则1:往数组里填东西或者删除东西,数组本身的引用计数不改变!!!!,变的是被拿去添加的元素,引用计数相应增减

    原则2:往view添加subview或者removeview,superView本身引用计数都不改变!!!变的是被拿去添加的subview,引用计数相应增减

    原则3:subview可分为两种,一种是不需要控制的静态view,一种是被设为成员变量长期控制的动态view。 假设subview添加到superview中,并且以后不打算做改变,则应这么写:

    uiview *subview = new subview;//subview:1

    //若是动态view,则是_subView = new subview;//subview:1

    [superView addSubView:subview];//subview:2, superview:1

    [subview release];//subview:1

    静态view:在dealloc中就不用再释放了!因为大原则是“谁申请谁释放”,你只申请了一次,自然只需要释放一次。剩下的1个引用什么时候减掉呢?当superView释放的时候自己释放掉!

    动态view:若是动态view,则完全可以跟静态view一样,这样的话Dealloc里面就是空空的,这也是可以的;另一种是在上述步骤中不做release操作,统统保留到dealloc中做






  • 相关阅读:
    yolo v1
    012. MVC5中Razor引擎使用模板页
    Centos 7 下, 安装odoo 10
    011. 解决VS2015中CS1528: Expected ; or = (cannot specify constructor arguments in declaration)
    010. VS2015创建MVC项目
    解决IE增强配置的问题
    解决Centos 7 下 tomcat字体异常 Font '宋体' is not available to the JVM
    tomcat7.0在centos7下中文乱码问题解决汇总
    windows服务器审核失败消息:事件ID: 861 进程标识符:904
    使用USBWriter做U盘启动盘后容量变小的解决办法
  • 原文地址:https://www.cnblogs.com/wengzilin/p/2398083.html
Copyright © 2011-2022 走看看