美文网首页iOS进阶
06.6-OC中block循环引用问题

06.6-OC中block循环引用问题

作者: 光强_上海 | 来源:发表于2020-06-14 23:04 被阅读0次

    block的循环引用

    我们新建一个工程,然后新建Person类,在main函数中编写如下测试代码:

    Person

    typedef void(^MyBlock)(void);
    
    @interface Person : NSObject
    
    @property (nonatomic, assign) int age;
    
    @property (nonatomic, copy) MyBlock block;
    @end
    
    
    @implementation Person
    
    - (void)dealloc {
        NSLog(@"%s", __func__);
    }
    @end
    

    main函数

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            Person *person = [[Person alloc] init];
            person.age = 10;
            
            person.block = ^{
                NSLog(@"%d",person.age);
            };
            
            person.block();
        }
        
        NSLog(@"222");
        return 0;
    }
    

    运行程序发现person对象没有正常释放,产生循环引用,示例图如下:

    image

    那么如何解决block的循环引用问题尼,我们可以使用下面两个关键字:

    • __weak
    • __unsafe_unretained

    我们先来使用__weak解决循环引用,代码如下:

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            
            Person *person = [[Person alloc] init];
            person.age = 10;
            
            __weak typeof(Person) *weakPerson = person;
    
            person.block = ^{
                // 在block内部再使用__strong,这样防止在block内部使用`person`对象时,`person`对象提前销毁
                __strong typeof(Person) *strongPreson = weakPerson;
                
                NSLog(@"%d",strongPreson.age);
            };
            
            person.block();
        }
        
        NSLog(@"222");
        return 0;
    }
    

    引用关系如图所示:

    image

    我们先来使用__unsafe_unretained解决循环引用,代码如下:

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            
            Person *person = [[Person alloc] init];
            person.age = 10;
            
            __unsafe_unretained typeof(Person) *weakPerson = person;
    
            person.block = ^{
                // 在block内部再使用__strong,这样防止在block内部使用`person`对象时,`person`对象提前销毁
                __strong typeof(Person) *strongPreson = weakPerson;
                
                NSLog(@"%d",strongPreson.age);
            };
            
            person.block();
        }
        
        NSLog(@"222");
        return 0;
    }
    

    引用关系如图所示:

    image

    既然__weak__unsafe_unretained都能解决循环引用,那它们有什么不同?

    __weak:当指针指向的对象销毁时,使用__weak修饰的指针的内存地址值会自动赋值为nil

    __unsafe_unretained:当指针指向的对象销毁时,使用__unsafe_unretained修饰的指针的内存地址值不变

    使用__unsafe_unretained修饰,当指针指向的对象销毁时,指针的内存地址不变,如果还使用这个指针来发送消息就容易导致野指针错误,所以在ARC环境下,我们还是优先选择使用__weak来解决block循环引用问题

    解决block循环引用总结如图:

    image

    讲解示例代码Demo地址:https://github.com/guangqiang-liu/06.6-BlockDemo6

    更多文章

    相关文章

      网友评论

        本文标题:06.6-OC中block循环引用问题

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