内存管理(二)

1.属性的内存管理


assign属性的内部实现

@property (nonatomic, assign) NSInteger age;

这行代码系统会自动帮我们在.h文件中声明好setter和getter方法,以及创建_age的实例变量并且在.m文件中实现


以上代码不需要我们自己写,但是如果在mrc中,setter和getter我们需要重写,因为会有内存问题具体如下:

(retain类型的对象内存管理)
setter问题一(野指针)
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString *name = [[NSMutableString alloc] initWithFormat:@"lisi"];
        Person *p = [[Person alloc] init];
        p.name = name;
        [name release];
        NSLog(@"%@", p.name);
        [p release];
    }
    return 0;
}

上述代码开启僵尸模式会报

message sent to deallocated instance 0x100603540

具体情况如下分析:

(这里NSString *name = [[NSMutableString alloc] initWithFormat:@"lisi"];我之所以用NSMutableString原因是因为NSString 不会出错,我猜测NSString不是在堆开辟空间的)

 

解决方法 :

在setter时并没有对引用计数器进行retain操作故

- setName:(NSString *)name

{

   [name retain];

  _name = name;

// 写成一句 _name = [name retain];

}

setter问题二(内存泄露)

 Person *person = [[Person alloc] init];
        
        NSString *name = [[NSString alloc] initWithFormat:@"张三"];
        [person setName:name];
        
        [name release];
        name = nil;
        
        NSLog(@"name = %@", [person name]);
        
        NSString *newName = [[NSString alloc] initWithFormat:@"李四"];
        [person setName:newName];
        [newName release];
         newName = nil;
        
        NSLog(@"%@", person.name);
        
        
        [person release];
        person = nil;

具体分析:

 解决办法:

- (void)setName:(NSString *)name

{

      [_name release];

      _name = [name retain];

}

以上这样写会出问题,比如

p.name = name; p.name = name; 

操作了两次,这样计数器就会出问题,具体问题自己想想

解决方法是

- (void)setName:(NSString *)name

{

if (name != _name)

{

       [_name release];

      _name = [name retain];

}

}

 

getter方法内存管理最好是采用

- (NSString *)name

{

return [[_name retain] autorelease];

}

这样写是苹果推荐写法,防止内存泄露

 

(copy 类型对象的管理)

相比较retain只需要将setter的  _name = [name retain];改为 _name = [name copy];

其他的就是一样的

因为assign类型的数据我们不用管的,其内存不是在堆上的,不是由我们管理的

但是在检测内存泄露(commd + shift + B 这快捷键是检测程序有没有内存泄露)时如果不写在写一遍会有内存泄露,这点有点问题

这里说的重写是指

@implementation Studnet

@synthesize age = _age

- (void)setAge:(NSInteger)age {

    _age = age;

} 

- (NSInteger)age {

    return _age;

}

不写这个会有泄露,具体原因还在探索中. (转载请注明出处).

  

posted @ 2016-04-04 15:42  ywhb  阅读(114)  评论(0)    收藏  举报