iOS底层系列之<12>--Block(五)循环引用

1、Part One

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        person.age = 10;
        person.personBlock = ^{
            NSLog(@"age is %d",person.age);
        };
        
        NSLog(@"----");
    }
    return 0;
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        person.age = 10;
        
        // __weak Person *weakPerson = person;
        __weak typeof(person) weakPerson = person;
        person.personBlock = ^{
            NSLog(@"age is %d",weakPerson.age);
        };
        
        NSLog(@"----");
    }
    return 0;
}

内存图分析
在这里插入图片描述

2、Part 2

  • 解决方案1

__weak 和__unsafe_unretained的区别:
__weak:不会产生强引用,指向的对象销毁时,会自动让指针置为nil(ARC环境下首选方案)
__unsafe_unretained:不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变(这种不安全,不常用)

  • 解决方案2(情况:必须调用block,才有可能调用置空方法)

使用__block

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        __block Person *person = [[Person alloc] init];
        person.age = 10;
        
        person.personBlock = ^{
            NSLog(@"age is %d",person.age);
            person = nil;
        };
        person.personBlock();
        
        NSLog(@"----");
    }
    return 0;
}

  • 为什么使用__block,然后将person = nil 就可以解决循环引用?
    1、先回顾下转换成c++代码(xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m)
 typedef void (*Block)(void);

// 1. __block修饰的那部分:__block Person *person = [[Person alloc] init];
struct __Block_byref_person_0 {
  void *__isa;
__Block_byref_person_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 Person *__strong person; // 后面使用的person指针,都是这个指针
};

// 2.person.personBlock = ^{ ... }
struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_person_0 *person; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_person_0 *_person, int flags=0) : person(_person->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

  • 图解,黄色标注的表示引用关系:
    在这里插入图片描述
  • 当执行personBlock 里面的 person = nil时候:
  • 绿色的就释放了,就不会造成循环引用了
    在这里插入图片描述
  • 如果是在MRC情况下:

1.因为MRC不支持弱引用的情况,所以可以使用__unsafe_unretained
2.使用__block解决
因为__block不会对对象产生强引用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值