美文网首页
Block内存管理

Block内存管理

作者: 言霏 | 来源:发表于2020-04-20 16:15 被阅读0次

    对block自身内存的管理

    对于block,有两个内存管理方法:Block_copy, Block_release;Block_copycopy等效,Block_releaserelease等效;
    不管是对block进行retian,copy,release,block的引用计数都不会增加,始终为1;

    • NSGlobalBlock:使用retain,copy,release都无效,block依旧存在全局区,且没有释放, 使用copyretian只是返回block的指针;
    • NSStackBlock:使用retain,release操作无效;栈区block会在方法返回后将block空间回收; 使用copy将栈区block复制到堆区,可以长久保留block的空间,以供后面的程序使用;
    • NSMallocBlock:支持retian,release,虽然block的引用计数始终为1,但内存中还是会对引用进行管理,使用retain引用+1, release引用-1; 对于NSMallocBlock使用copy之后不会产生新的block,只是增加了一次引用,类似于使用retian;

    对引用变量的内存管理

    如果该block为NSMallocBlock或者被copy成NSMallocBlock类型则其引用的外界变量的引用计数会被+1,当block释放时外界变量的引用计数-1,而block为NSStackBlockNSGlobalBlock类型时外界变量的引用计数不会变,例子NSMallocBlock

    - (void)testBlock {
        NSObject *obj = [[NSObject alloc] init];
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
        void(^normalBlock)(int, int) = ^(int a, int b) {
            NSLog(@"normalBlock = %d %@", a + b, obj);
        };
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
        NSLog(@"normalBlock %@", normalBlock);
        
        void(^normalCopyBlock)(int, int) = [normalBlock copy];
        NSLog(@"normalCopyBlock %@", normalCopyBlock);
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
    }
    

    输出:

    2020-04-20 16:03:56.412850+0800 obj.retainCount = 1
    2020-04-20 16:03:56.414244+0800 obj.retainCount = 1
    2020-04-20 16:03:56.414685+0800 normalBlock <__NSStackBlock__: 0x7ffeefbff538>
    2020-04-20 16:03:56.414798+0800 normalCopyBlock <__NSMallocBlock__: 0x100625400>
    2020-04-20 16:03:56.414985+0800 obj.retainCount = 2
    

    例子NSGlobalBlock

    NSObject *obj = nil;
    - (void)testBlock {
        obj = [[NSObject alloc] init];
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
        void(^normalBlock)(int, int) = ^(int a, int b) {
            NSLog(@"normalBlock = %d %@", a + b, obj);
        };
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
        NSLog(@"normalBlock %@", normalBlock);
        
        void(^normalCopyBlock)(int, int) = [normalBlock copy];
        NSLog(@"normalCopyBlock %@", normalCopyBlock);
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
    }
    

    输出:

    0-04-20 16:14:01.728789+0800 obj.retainCount = 1
    2020-04-20 16:14:01.729195+0800 obj.retainCount = 1
    2020-04-20 16:14:01.729499+0800 normalBlock <__NSGlobalBlock__: 0x100002030>
    2020-04-20 16:14:01.729582+0800 normalCopyBlock <__NSGlobalBlock__: 0x100002030>
    2020-04-20 16:14:01.729636+0800 obj.retainCount = 1
    

    循环引用

    • __block 在MRC中使用,NSMallocBlock类型的block不会对__block修饰的的变量引用计数+1,从而消除循环引用,并且可以让该变量在block内被赋值;在ARC中使用__block只是可以让该变量在block内被赋值。
    • __weak 在ARC中使用,作用和__block一样,从而消除循环引用;在非ARC中不可以使用__weak;

    MRC下例子:

    @property (nonatomic, copy, readwrite) void (^copyBlock)(void);
    
    - (void)testBlock {
        NSObject *obj = [[NSObject alloc] init];
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
        self.copyBlock = ^() {
            NSLog(@"copyBlock = %@", obj);
        };
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
        NSLog(@"normalBlock %@", self.copyBlock);   
    }
    

    输出:

    2020-04-20 16:23:12.712386+0800 obj.retainCount = 1
    2020-04-20 16:23:12.713195+0800 obj.retainCount = 2
    2020-04-20 16:23:12.713557+0800 normalBlock <__NSMallocBlock__: 0x100707d40>
    

    MRC下例子:

    @property (nonatomic, copy, readwrite) void (^copyBlock)(void);
    
    - (void)testBlock {
        __block NSObject *obj = [[NSObject alloc] init];
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
        self.copyBlock = ^() {
            NSLog(@"copyBlock = %@", obj);
        };
        NSLog(@"obj.retainCount = %ld", obj.retainCount);
        NSLog(@"normalBlock %@", self.copyBlock);
    }
    

    输出:

    2020-04-20 16:28:59.888767+0800 obj.retainCount = 1
    2020-04-20 16:28:59.889190+0800 obj.retainCount = 1
    2020-04-20 16:28:59.889454+0800 normalBlock <__NSMallocBlock__: 0x1006518e0>
    

    参考:
    https://www.jianshu.com/p/4a6dca34d980

    相关文章

      网友评论

          本文标题:Block内存管理

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