首页 > 其他 > 详细

8.内存管理高级

时间:2016-02-17 20:58:23      阅读:196      评论:0      收藏:0      [点我收藏+]
属性的内存管理,属性中最重要的语义特性
assign 基本数据类型(char,short,int,float,double)
retain 对象类型
copy 对象类型,且遵守了<NSCopying>协议

assign下的属性内部实现:直接赋值的方法
@property (nonatomic, assign)NSString *name;

setter 方法
- (void)setName:(NSString *)name {
          _name = name;
}
getter 方法
- (NSString *)name {
           return _name;
}
main.m代码
NSString *name = [NSString alloc] initWithFormat:@“张三”];
Person *p = [[Person alloc] init];
p.name = name;
[name release];
NSLog(@“%@”,p.name);
[p release];
该方法容易出现野指针异常,name已经被释放,在去访问p.name就会出现野指针。


retain下的属性内部实现:间接赋值
@property (nonatomic, retain) NSString *name;
setter方法
-(void)setName:(NSString *)name {
           第一次时,_name是空指针,执行release没有任何变化,第二次_name有值,将第一次的_name释放。
          if(_name != name) {
              [_name release];
               _name = [name retain];
          }
}
getter方法
- (NSString *)name {
          getter方法是安全的,使用getter方法不会改变原来实例变量的引用计数
          return [[_name retain] autorelease];
}

copy方法与retain方法一样,间接赋值。


代码的演示:
@property (nonatomic, copy)NSString *name;
@property (nonatomic, copy)NSString *gender;

Person *p = [[Person alloc]initWithName:@"zhangsan” gender:@"m"];
执行初始化中的setter方法,将常量区的zhangsan拷贝到堆区,定义一个指针p指向堆区首地址。

    p.name = @“lisi”;
    p.gender = @"f";
name属性定义copy,copy首先释放了堆区中的_name实例变量(zhangsan副本被释放),赋值lisi,执行一次setter方法,指针指向从常量区拷贝到堆区的lisi的首地址。

    NSLog(@"person‘s name is %@, gender is %@",p.name, p.gender);
    [p release];
释放p,最后留下了lisi实例变量,造成内存泄漏。



dealloc是NSObject的一个实例方法,用于回收alloc开辟的内存空间。
在引用计数为0时,由系统自动调用。
copy、retain等修饰的属性的实例变量的内存泄漏问题(setter方法),可以在dealloc中释放类的实例变量。

重写dealloc方法:
技术分享

便利构造器的内存管理,加上autorelease
技术分享
在MRC中,对象如果是遍历构造器创建的,不要释放此对象,因为在创建遍历构造器时已经做了autorelease去释放。


集合的内存管理
集合在作为类的对象初始化时:
@property (nonatomic, retain)NSMutableArray *mArr;
_mArr = [[[NSMutableArray alloc]initWithCapacity:0] autorelease];
_mArr是getter方法,只有alloc,引用计数为1,在后面加autorelease或者重写dealloc方法中释放[_mArr release]

self.mArr = [[[NSMutableArray alloc]initWithCapacity:0] autorelease];
self.mArr是getter方法,alloc引用计数从0到1,之后,setter方法引用计数加1,在后面加上autorelease,还要在dealloc方法中加[_mArr release],释放两次。

加入容器的对象会被执行一次retain操作,引用计数加1
移除容器的对象会被执行一次release操作,引用计数减1
当容器自身释放时,会向容器中的所有储存的对象发送一次release消息


KVC(Key-Value-Coding),键值编码,是一种间接访问实例变量的方法,Key:键,用与标识实例变量,Value:实例变量对应的值
KVC在没有get/set方法,同样可以读写。
第一种
设置值:setValue:forKey:
取值:valueForKey:

第二种
设置值:setValue:forKeyPath:
取值:valueForKeyPath:
通过路径为实例变量赋值和取值

第三种:
setValuesForKeysWithDictionary:


字典中取值和赋值时,避免赋值匹配出现的崩溃问题,可以重写以下两种方法:
技术分享

KVC实现机制:
1、检查是否在setter和getter方法中有实例变量的方法。
2、如果没有上述方法,检查是否存在实例变量的命名。
3、如果扔为找到,则调用valueForUndefinedKey:和setValue:forUndefinedKey:方法。这个方法默认实现都是抛出异常。

8.内存管理高级

原文:http://www.cnblogs.com/aoliaoli/p/5196452.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!