美文网首页
《iOS多线程和内存管理》的幺蛾子01——retaincount

《iOS多线程和内存管理》的幺蛾子01——retaincount

作者: ShayneFcf | 来源:发表于2018-01-25 10:35 被阅读7次

将项目设置成MRC的项目:
Build Setting——选Levels——搜索Objective-C Automatic Reference Counting,将其改为NO

1、内存管理/引用技术:
定一个总的方针政策吧:

  •   自己创建的对象,自己持有;(自己养的狗,肯定自己遛呀)
    
  •   非自己创建的对象也可以自己持有;(不是自己养的就不能遛了?)
    
  •   不再需要自己持有的对象时释放;(利用完了就干掉)
    
  •   非自己持有的对象,无法释放;(动别人家的狗,咬不死你)
    

内存管理的四个关键词:生成、持有、释放、废弃!与之对应的OC的主要方法:
生成并持有:alloc、new、copy、mutablecopy
非自己生成想持有:retain
释放:release
废弃:dealloc
调用alloc和retain方法后,引用计数+1;release执行后,引用计数-1;引用计数为0后,调用dealloc进行释放!

接下来逐个分析一下各个方针政策:
自己生成的对象,自己所持有:(alloc、new、copy、mutablecopy)
使用以下名称开头的方法名意味着自己生成的对象只有自己持有(注意是“用以下名称开头的方法名”):

  • alloc
  • new
  • copy
  • mutableCopy

到这里,一些有强迫症的同志估计就要问了,难道所有以这几个词为开头的方法生成的对象都是自己持有吗?
这里,我就要指出一个我们猿狮们都听说过的一个词汇——驼峰命名法。是的,你没有听错,所有以驼峰命名法命名,且使用了上诉几个词汇开头的方法生成的对象都是自己持有的,而像什么copying,mutableCopyed等这种以假乱真、冒名顶替的方法,对它嗤之以鼻就好了。

非自己生成的对象,自己也能持有:(retain)
那想要持有其他人的对象(肯定不是自己持有的)怎么办呢?使用retain。别人家养的狗,还不能套吗?retain就是那套狗的工具,套上了就是你的了。

不再需要自己持有的对象时释放:(release、autorealease)
该放手时就放手。release
死后也要撒手。autorelease
release 立即释放
autorelease 对象在超出指定的生存范围时,自动释放池pool结束时调用release释放。这里要特别说明一下,系统所有类方法创建的对象都是调用过autorelease实例方法的,这样就不会引起有内存没有泄露的情况

非自己持有的对象,无法释放
这个很好理解了,不是自己的对象,肯定不能自己释放的。如果在程序中释放了非自己持有的对象将导致崩溃,同样的,重复释放也会导致崩溃。

用一波代码展示一下这节的内容:

  - (void)retainCount {

    //自己生成的对象,自己持有

    NSObject * obj1 = [NSObject new];

    printf("obj1 retainCount = %lu\n",(unsigned long)obj1.retainCount); // 1

    [obj1 release];

    //非自己生成的对象,也可以自己持有

    NSObject *  obj2 = [NSObject new];

    printf("obj2 retainCount = %lu\n",(unsigned long)obj2.retainCount); //1

    NSObject *  obj3 = [obj2 retain];

    printf("obj2 retainCount = %lu\n",(unsigned long)obj2.retainCount); //2

    printf("obj3 retainCount = %lu\n",(unsigned long)obj3.retainCount); //2

    [obj2 release];

    printf("obj2 retainCount = %lu\n",(unsigned long)obj2.retainCount); //1

    printf("obj3 retainCount = %lu\n",(unsigned long)obj3.retainCount); //1

    [obj3 release];

    //obj2和obj3是命运共同体,实际上他们就是别名的作用,所以他们的引用计数一直都是一样的


    NSObject * test = [self objc]; //这里objc对象是存在的,但是test不持有objc的。

    printf("test retainCount = %lu\n",(unsigned long)test.retainCount); //1

    //    [test release]; //释放自己不持有的对象,这里会导致崩溃

    NSObject * test2 = [[self objc] retain]; //非自己生成的对象只能通过retain才能持有

    printf("test2 retainCount = %lu\n",(unsigned long)test2.retainCount); //2

    [test2 release];

    printf("test2 retainCount = %lu\n",(unsigned long)test2.retainCount); //1

    //到了这里实际上objc的引用计数还有1,而这个引用计数就是通过函数的autorelease在之后释放的。

}

- (NSObject * )objc{

    NSObject *  objc = [[NSObject alloc]init];

    printf("objc retainCount = %lu\n",(unsigned long)objc.retainCount); //1

    //autorelease 不立即释放,

    return [objc autorelease];

}

相关文章

网友评论

      本文标题:《iOS多线程和内存管理》的幺蛾子01——retaincount

      本文链接:https://www.haomeiwen.com/subject/fynmaxtx.html