关于__autoreleasing,你真的懂了吗?

上一篇文章介绍了__unsafe_unretained

这里我们要借助__unsafe_unretained来理解__autoreleasing,童鞋们肯定会说__autoreleasing,这么简单,就是将指向的对象延迟销毁,这里我要将我研究__autoreleasing的过程中遇到的坑一一分析出来,如果你也遇到过,那我们可以一起讨论一下,或者你觉得我哪里分析得不对,请提出来,因为我也在学习中,如果你还没有遇到过我提出来的这些问题,你也可以看看。

这里插入一点小知识:

    id __strong obj0;
    id __weak obj1;
    id __autoreleasing obj2;
    
    // __strong,__weak,__autoreleasing可以保证附有这些修饰符的自动变量初始化为nil
    
    // 上面源码和下面效果等同
    
    id __strong obj0 = nil;
    id __weak obj1 = nil;
    id __autoreleasing obj2 = nil;
//在文件中引入以下声明即可使用这两个函数
    extern void _objc_autoreleasePoolPrint();//打印注册到自动释放池中的对象
    extern uintptr_t _objc_rootRetainCount(id obj);//获取对象的引用计数


在编译器选项“-S”的同时运行clang,可以取得程序汇编输出,如:

clang -S 文件名

     

     /****************以下如果未特别说明,都是在ARC环境下****************/

     /********************分割线************************/

    

前言:

这里先说几个坑

第一个坑,首先举两个例子:

//例一
    id __unsafe_unretained obj1 = nil;
    {
        id  obj0 = [NSMutableArray array];
        [obj0 addObject:@"obj"];
        obj1 = obj0;
        NSLog(@"obj0 = %@", obj0);
    }
    
    NSLog(@"obj1 = %@", obj1);

//例二:
    id __unsafe_unretained obj1 = nil;
    {
        id  obj0 = [[NSMutableArray alloc]init];
        [obj0 addObject:@"obj"];
        obj1 = obj0;
        NSLog(@"obj0 = %@", obj0);
    }
    
    NSLog(@"obj1 = %@", obj1);

看到这两个例子,编译执行,都会在最后一条语句崩溃掉,你肯定会问我,它们有啥区别啊,仅仅是obj0对象的创建方式不一样,是的,我待会就要分析它们崩溃的原因,分析中你就会发现,这两种创建方式在ARC下其实是有区别的,虽然都不用我们自己来管理内存的释放,但是,理解一下底层的ARC机制也是好的。

分析:

这两个例子中,obj0在中括号也就是作用域内,是强引用可变数组对象的,作用域外obj0强引用失效,并且没有其他指针强引用这个对象,所以自动释放持有的对象,obj1就相当于野指针,访问野指针就会崩溃,这些上一节已经分析过了,我们继续看下一个例子:

//例三:
    id __unsafe_unretained obj1 = nil;
    
    {
        id obj0 = [NSMutableArray arrayWithObjects:@"obj",nil];
        obj1 = obj0;
        NSLog(@"obj0 = %@", obj0);
    }
    
    NSLog(@"obj1 = %@", obj1);

编译执行,正常打印信息:

2016-11-13 16:14:58.373 DebugDemo[3605:119189] obj0 = (

obj

)

2016-11-13 16:14:58.374 DebugDemo[3605:119189] obj1 = (

obj

) 

怎么回事,为什么没有崩溃,说好的野指针呢?这会有木有觉得自己掉坑里了,反正我当时是一脸懵逼...

问题我们先留在这里,我们先来看看编译器ARC的实现,再来详细分析为什么


再来说说第二个坑

+ (id)Object
{
return [NSMutableArray array];
}
+ (id)allocObject
{
return [NSMutableArray array];
}

执行以下代码:

//例四
id __unsafe_unretained obj1 = nil;
{
id obj0 = [[self class] Object];
[obj0 addObject:@"obj"];
obj1 = obj0;
NSLog(@"obj0 = %@", obj0);
}
NSLog(@"obj1 = %@", obj1);

执行结果,正常打印,不会崩溃

那么我们将类方法修改成如下:

+ (id)Object
{
NSMutableArray *marr = [NSMutableArray array];
return marr;
}

再执行,崩溃,这里我们标记为例五

我们再调用以alloc开头的类方法:

//例六
id __unsafe_unretained obj1 = nil;
{
id obj0 = [[self class] allocObject];
[obj0 addObject:@"obj"];
obj1 = obj0;
NSLog(@"obj0 = %@", obj0);
}

NSLog(@"obj1 = %@", obj1);

还是崩溃


扩展:如果将两个类方法的实现换成如下,则会怎么样;

return [[NSMutableArray alloc]init];

答案是都会崩溃

     /********************分割线************************/

我们先来看看alloc的情况

{
     id __strong obj = [[NSObject alloc] init];
}

我们来看看它的模拟源代码:

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值