block原理学习(4.对象类型的auto变量)

1、定义一个简单的block:

		MJBlock block;
        {
            MJPerson *person = [[MJPerson alloc] init];
            person.age = 10;
            block = ^{
                NSLog(@"---------%d", person.age);
            };
        }
        NSLog(@"------");

第二个nslog打印完成之后,person不会销毁,因为block有个指针指向了外面的person对象,block在堆上,是malloc类型的。block不销毁,person也不会销毁。但是如果改成mrc环境,栈上的block不会强引用auto对象。但是如果person用__weak修饰的话,person就会先销毁。
上面的block改成下面这样:

		MJBlock block;
        {
            MJPerson *person = [[MJPerson alloc] init];
            person.age = 10;
            __weak MJPerson *weakPerson = person;
            block = ^{
                NSLog(@"---------%d", weakPerson.age);
            };
        }
        NSLog(@"------");

这种情况下用之前的clang xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m转变成底层c++代码会报错 cannot create __weak reference in file using manual reference 因为weak是弱引用是在runtime下进行的,所以用xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m转换之后:

typedef void (*MJBlock)(void);
struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  MJPerson *__weak person;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, MJPerson *__strong _person, int flags=0) : person(_person) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  MJPerson *__strong person = __cself->person; // bound by copy
  NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_c41e64_mi_0, ((int (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("age")));
            }
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {
_Block_object_assign((void*)&dst->person, (void*)src->person, 3/*BLOCK_FIELD_IS_OBJECT*/);
}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {
_Block_object_dispose((void*)src->person, 3/*BLOCK_FIELD_IS_OBJECT*/);
}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

之前的MJPerson * person;也转换成了MJPerson *__weak person;

总结如下:
当block内部访问了对象类型的auto变量时
1、如果block是在栈上,不论是强指针还是弱指针都不会去对auto对象进行强引用。
2、如果block被拷贝到堆上。在arc环境下,当一个block被强引用引用着,就会进行copy操作,如果block进行copy操作的时候会调用内部的_Block_object_assign函数 ,调用这个函数会根据外部的auto对象的修饰关键字MJPerson *__weak person或者MJPerson *__strong person对auto进行强引用或者弱引用
3、如果block从堆上移除。会调用block内部的dispose函数,dispose函数内部会调用_Block_object_dispose函数,_Block_object_dispose函数会自动释放引用的auto变量,类似于release操作。
在这里插入图片描述面试题:

    MJPerson *p = [[MJPerson alloc] init];
    __weak MJPerson *weakP = p;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"1-------%@", p);
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2-------%@", weakP);
        });
    });
    NSLog(@"-----------");

经过nslog1跟nslog2位置的变换,得出一个结论,person的释放时间是看person强引用什么时候释放,不用管弱引用释放

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值