美文网首页OC 底层原理笔记
11 block-循环引用详解

11 block-循环引用详解

作者: zysmoon | 来源:发表于2020-01-20 14:41 被阅读0次
    循环引用问题
    1653926-54f6d705c5a184a6.png

    循环引用代码例子如下

    #import <Foundation/Foundation.h>
    
    typedef void(^CSBlock)(void);
    @interface Person : NSObject
    /** age*/
    @property(nonatomic,assign)int age;
    /** blokc*/
    @property(nonatomic,copy) CSBlock block;
    @end
    
    @implementation Person
    - (void)dealloc {
        NSLog(@"%s",__func__);
    }
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Person *person = [[Person alloc] init];
            person.age = 100;
            person.block = ^{
                NSLog(@"age = %d",person.age);
            };
        }
        NSLog(@"end");
        return 0;
    }
    
    

    运行结果如下

    1653926-08107db4bcb969d2.png
    解决循环引用问题 - ARC
    • 用__weak、__unsafe_unretained解决
      • __weak:不会产生强引用,指向的对象销毁时,会自动让指针置为nil
      • __unsafe_unretained:不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变
    1653926-6a60dc36706807c7.png

    [图片上传中...(1653926-15dd8d8892a980c9.png-f61152-1542180021728-0)]

    代码佐证

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // __weak:不会产生强引用,指向的对象销毁时,会自动让指针置为nil
            // __unsafe_unretained:不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变
    
            Person *person = [[Person alloc] init];
            person.age = 100;
    //        __weak typeof(person) weakPerson = person;
            __unsafe_unretained typeof(person) weakPerson = person;
            person.block = ^{
                NSLog(@"age = %d",weakPerson.age);
            };
        }
        NSLog(@"end");
        return 0;
    }
    
    
    • 用__block解决(必须要调用block)
    1653926-15dd8d8892a980c9.png

    代码佐证

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

    运行结果

    1653926-2cf37154fc773ee4.png
    解决循环引用问题 - MRC
    • 用__unsafe_unretained解决(MRC环境下不支持__weak)
    1653926-7cbc0749490c19e4.png
    • 用__block解决
    1653926-8938b5b745933ed7.png

    代码例子佐证

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
             // MRC环境下
            // MRC不支持__weak的
            __block Person *person = [[Person alloc] init];
            person.age = 10;
            person.block = ^{
                NSLog(@"age is %d", person.age);
            };
            [person release];
        }
        NSLog(@"end");
        return 0;
    }
    
    

    运行结果如下

    1653926-b8c895e256ef066c.png

    面试题 - Block

    block的原理是怎样的?本质是什么?

    封装了函数调用以及调用环境的OC对象

    __block的作用是什么?有什么使用注意点?

    详情请看iOS-block底层原理详解之__block属性

    block的属性修饰词为什么是copy?使用block有哪些使用注意?
    • block一旦没有进行copy操作,就不会在堆上
    • 使用注意:循环引用问题
    block在修改NSMutableArray,需不需要添加__block?
    • 不需要

    本文参考:
    路飞_Luck (https://www.jianshu.com/p/07f7b96bb03f)
    以及借鉴MJ的教程视频
    非常感谢.


    项目演示代码
    iOS-block-cycle

    相关文章

      网友评论

        本文标题:11 block-循环引用详解

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