OC 内存的高级管理

属性的属性, 是对内存的优化,! 这里具体讲解

  1. 属性的内部实现原理
  • assign
    assign的内部实现 // 定义变量的时候, 无原子性, 语义设置为assign;
    @property(nontatomic , assign)NSString *name;
    setter 方法
    - (void)setName:(NSString *)name {
    _name = name;
    }
    getter 方法
    - (NSString *)name {
    return _name;
    }
    调用!
    NSString *name = [[NSString alloc] initWithFormat:@"张三"];// 此时计数为1
    Person *p = [[Person alloc] init]; p引用计数为1
    [p setName:name] p指向存储name那块空间区域, p引用计数为1, name 引用计数为1;
    [name release] 则name计数减1为0, 则name那块空间被释放!
    NSLog:(@"%@", [p name]); p所指向的那块区域已不存在 ,p变为了野指针!也就是野指针异常 !
    [p release];
    所以, 当用alloc 创建的时候,出现了野指针的现象!

  • retain 把语义设置成retain试试
    @property(nontatomic , retain)NSString *name;
    - (void)setName:(NSString *)name {
    if (_name != name)
    [_name release];
    _name = [name retain];
    }
    getter方法
    -(NSString *)name{
    return[[_name retain ]autorelease];
    }

    按照以上方法再来一遍

      NSString *name = [[NSString alloc] initWithFormat:@"张三"]; // name引用计数为1 
      Person *p = [[Person alloc] init];  // p的引用计数为1;
      [p setName:name];  // 经内部实现, name引用计数为2; p指向name那块空间
      [name release];    // name引用计数为 1;
      NSLog(@"%@", [p name]);  
    
      NSString *newName = [[NSString alloc] initFormat:@"李四"];    // newName 计数为1;
      [p setName: newName];          {此时, 经过retain的内部实现, [_name release], 则name计数为0, name自动释放, 接着在执行_name = [name retain]; };           
      [newName release];  newName计数-1, 所以newName引用计数为1  
      [p release];  p引用计数为0, 自动释放
    
     此时, newName还没有完全被释放, 所以还有内存问题!!
    
  • copy 把语义设置成copy
    @property(nonatomic, copy)NSString *name;
    copy中的setter方法
    - (void)setName:(NSString *)name{
    if (_name != name){
    [_name release];
    _name = [name copy];
    }
    }
    getter方法;
    - (NSString *)name{
    return [[_name retain ] autorelease];
    }
    引用
    NSString *name = [[NSString alloc] initWithFormat:@"张三"]; //name引用计数为1
    Person *p = [[Person alloc] init]; // p 引用计数为1;
    [p setName: name]; // 拷贝了一份, 拷贝的_name 引用计数为1;p 指向 _name;
    [name release] // name 引用计数为0, 自动释放;
    NSLog(@"%@", [p name]);

     NSString *newName = [[NSString alloc] initWithFormat:@"李四"];  // setName引用计数为1;
     [p setName:newName];    //内部实现 [ _name release]  则name计数为0, 自动释放;_name = [name copy]; 则 copy了一份 newName 计数为1; p指向newName;
     [newName release];    // newName 计数为0;
     NSLog(@"%@", [p name]);
     [p release];   p 引用计数为0,  被释放,
    

    这有存在了与retain一样的问题, _newName没有被释放; 怎么解决?? 在delloc中处理

  • dealloc
    dealloc方法, 这个方法在引用计数为0的时候, 由系统自动调用, 使其释放! 因而可以重写delloc方法, 在调用的时候, 把上边有setter方法遗留下来的没有释放的给释放掉!

    比如 在person.m中重写delloc方法
    - (void)dealloc {
    [_name release]; // 释放setter方法泄露的实例变量
    [super dealloc];
    }

    当 p release之后, 引用计数变为0, 此时会调用dealloc方法, 因为释放了setter方法泄露的实例变量

  • dealloc的注意事项
    注意: 永远不要手动调用dealloc, 在dealloc方法的最后一行必须要写[super dealloc];

  • 遍历构造器的内存管理
    Person.m 中
    +(id)personWithName:(NSString *)name{
    Person *p = [[Person alloc] initWithName: name]; // 若是用遍历构造器, 这里的alloc 何时释放?
    return p;
    }
    若在 return p; 之前 [p release], retrun 则无返回;
    若在 retrun p; 之后[p release], 则也会出现, 无值现象;
    最佳方案
    +(id)personWithName:(NSString *)name{
    Person *p = [[Person alloc] initWithName: name];
    return [p autorelease];
    }

    return [p autorelease]是最完美的解决方案, 既不会出现内存泄露, 也不会产生野指针;

内存管理
NSString *houseOfMM = [[NSString alloc] initWithString:'装梵几的三室两厅'];

上面一段代码会执行以下两个动作:

  1. 在堆上分配一段内存用来存储@' 装梵几的三室两厅 ',比如:内存地址为0X1111 内容为' 装梵几的三室两厅'
  2. 在栈上分配一段内存用来存储 houseForWife ,比如:地址为 0XAAAA 内容自然为0X1111
    下面分别看下(assign,retain,copy):
  • assign的情况:
    NSString * myHouse = [ houseOfMM assign ];
    此时 myHousehouseOfMM 完全相同,地址都是 0XAAAA ,内容为 0X1111 ,即 myHouse 只是 houseOfMM 的别名,对任何一个操作就等于对另一个操作。因此 retainCount 不需要增加.(同进同出,关系好,一把钥匙,给我拿着)
  • retain的情况:
    NSString * myHouse = [ houseOfMM retain ];
    此时 myHouse 的地址不再为 0XAAAA ,可能为 0XAABB ,但是内容依然为 0X1111.因此 myHousehouseOfMM 都可以管理' 装梵几的三室两厅 '所在的内存。因此 retainCount 需要增加1.(有些独立,各自进出,两把钥匙)
  • copy的情况:
    NSString * myHouse = [ houseOfMM copy ];
    此时会在堆上重新开辟一段内存存放@'装梵几的三室两厅',比如0X1122,内容为@'装梵几的三室两厅',同时会在栈上为myHouse分配空间,比如地址:0XAACC,内容为0X1122,因此retainCount增加1供myHouse来管理0X1122这段内存.
    (两套@'装梵几的三室两厅',条件好,分居了,房子一人一套,所以钥匙一人一把。)
  • 什么时候用assign,当然是破房子,简装的房子拉
    基础类型(简单类型,原子类型):NSInteger,CGPoint,CGFloat,C数据类型(int,float,double,char等)
  • 什么时候用copy
    含有可深拷贝的mutable子类的类,如NSArray,NSSet,NSDictionary,NSData的,NSCharacterSet,NSIndexSet,NSString
    (可深度拷贝的房子)
    但是NSMutableArray这样的不可以,Mutable的不能用copy,不然初始化会有问题。切记
  • 什么时候用retain
    其他NSObject和其子类对象好嘛 (大多数)
    ARC中的strong相当于非ARC中的retain,ARC来了以后多搞一把钥匙就strong了啦。
  1. collection的内存管理
    collection 就是NSArray, NSDictionary, NSSet.....等容器类;
    collection 会自助管理自己内部的元素;
    加入collection中的对象会被retain;
    移除出collection的对象会被release;
    cellection被释放会对内部所有对象release;

  2. 多态;

    多态的特点;
    父类指针可以指向不同的子类对象;
    允许在多个类中定义同一个消息接口;
    可以屏蔽不同子类对象之间的差异, 写出通用代码;
    适应需求的不断变化;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容