[objective-C] 08.内存管理2

属性的内部实现原理:
  1. 属性的语义特性以及使用范围:
    assign
    retain
    copy
  2. assign下的属性内部实现:

    @property (nonatomic, assign) NSString *name;

    #pragma mark setter方法

    - (void)setName:(NSString *)name

    {

        _name = name;

    }

    #pragma mark getter方法

    - (NSString *)name

    {

        return _name;

     

    }

    // 对于上面的实现,很容易产生内存问题,比如:

    NSString *name = [[NSString alloc] initWithFormat:@"小黑"];

    Person *person = [[Person allocinit];

    [person setName:name];

    [name release];

    NSLog(@"person.name = %@", [person name]); // 此处会出现野指针异常

    [person release];

    // 在内存被系统回收之后,还在使用。assign适合基本数据类型,基本数据类型不会引起内存问题。

  3. retain下的属性内部实现:

    #pragma mark setter方法

    - (void)setName:(NSString *)name

    {

        if (_name != name) {

            [_name release];

            _name = [name retain];

        }

    }

    #pragma mark getter方法

    - (NSString *)name

    {

        return [[_name retain] autorelease];

    }

    // Main.m

    NSString *name = [[NSString alloc] initWithFormat:@"小绿"]; // name引用计数为1

    Person *p = [[Person allocinit]; // p应用技数为1

    [p setName:name]; // name引用计数为2setName:内部执行了retain方法

    [name release]; // name引用计数为1

    NSLog(@"%@", [p name]);

    NSString *newName = [[NSString allocinitWithFormat:@"小白"]; // newName引用计数为1

    [p setName:newName]; // name引用计数为0newName引用计数为2

    [newName release]; // newName引用计数为1

    NSLog(@"%@", [p name]);

    [p release]; // p引用计数为1

    // 上面两处NSLog(@"%@", [p name]); 都不会引起野指针异常。每次[p setName:xx]

    都会先释放旧的对象,retain新的对象,即:name引用计数先减1,然后newName引用计数加1。上面的代码执行完毕后,name引用计数为0,然后anotherName引用计数加1。上面的代码执行完毕后,name引用计数为0name所占的内存被系统回收了,_name引用计数为1,仍然占有内存,p引用计数为0p所占的内存被系统回收。(代码执行完毕时_name占有的内存没有释放,引起了内存泄露)苹果为了保证程序的安全,retain对应的getter方法是先retainautorelease

    // retain适用于对象类型的属性



  4. copy下的属性内部实现:

    #pragma mark setter方法

    - (void)setName:(NSString *)name

    {

        if (_name != name) {

            [_name release];

            _name = [name copy];

        }

    }

    #pragma mark getter方法

    - (NSString *)name

    {

        return [[_name retain] autorelease];

    }

    // main.m文件

    NSString *name = [[NSString alloc] initWithFormat:@"张三"]; // name引用计数为1

    Person *p = [[Person allocinit]; // p引用计数为1

    [p setName:name]; // name引用计数为1, _name引用计数为1, setName:内部name执行了copy方法

    [name release]; // name引用计数为0, name占有的内存被释放

    NSLog(@"%@", [p name]); // 此处打印的是_name

    NSString *newName = [[NSString allocinitWithFormat:@"小华"]; // newName引用计数为1

    [p setName:newName]; // _name先是引用计数为0newName引用计数为1_name引用计数为1,因为setName:内部[newName copy];

    [newName release]; // newName引用计数为0

    NSLog(@"%@", [p name]); // 打印的是_name

    [p release]; // p引用计数为0

    // 上面的两处NSLog(@"%@", [p name]); 都不会引起野指针异常。每次[p setName:xx];都会先释放旧的对象,copy新的对象,即:_name引用计数为先减1,变为0,然后_name = [newName copy], _name引用计数变为1;下次如果给p设置新的名字anotherName_name引用计数先减1,变为0,然后_name = [anotherName copy], _name引用计数为1。上面的代码执行完毕后,name应用技术为0name所占内存被系统回收了,newName引用计数为0,所占的内存被系统回收,p引用计数为0p所占的内存被系统回收。_name引用计数为1,占用着内存,不能得到释放。(代码执行完毕时_name占有的内存没有释放,引起了内存泄露)苹果为了保证程序的安全,retain对应的getter方法先是retainautorelease

    // copy适用于接受了NSCopying协议的对象,因为只有接受了NSCopying协议,对象才能执行copy操作




了解dealloc:
  1. 什么是dealloc?
    dealloc是NSObject的一个实例方法,与alloc对应用于回收开辟的内存空间
    这个方法在对象引用计数为0时,由系统自动调用
    通常我们在dealloc中释放类的实例变量
  2. 如何使用dealloc?

    // Person.m

    - (void)dealloc

    {

        [_name release]; // 释放setter方法泄露的

        [super dealloc];

    }

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



遍历构造器方法的实现原理:
  1. Person类的便利构造器:

    // Person.m

    + (id)personWithName:(NSString *) name

    {

        Person *p = [[Person allocinitWithName:name];

        return p;

    }

    // 上面我们初始化的p对象,我们alloc之后,要在什么时候释放呢????

    // 正确写法

    + (id)personWithName:(NSString *) name

    {

        Person *p = [[Person allocinitWithName:name];

           return [p autorelease];

    }

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



collection的内存管理:
  1. collection:
    collection就是NSArray,NSDictionary,NSSet...等容器类
    collection会自主管理自己内部的元素
  2. 加入collection中的对象会被retain
  3. 移除出collection的对象会被release
  4. collection被释放会对内部所有对象release
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值