美文网首页
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内存管理实例分析

    Block内存管理实例分析 Block内存管理实例分析

  • Block内存管理

    对block自身内存的管理 对于block,有两个内存管理方法:Block_copy, Block_release...

  • iOS内存管理详解

    目录 block内存管理 autorelease内存管理 weak对象内存管理 NSString内存管理 new、...

  • Block 使用总结

    Block 内存管理: Block 内存主要分派到 NSGlobalBlock(data area),NSMall...

  • iOS面试之Block大全

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

  • iOS面试之Block模块

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

  • Block

    一、Block本质 二、 BlocK截获变量 三、__block 修饰变量 四、Block内存管理 五、Block...

  • Block

    Block介绍 截获变量 __block修饰符 Block的内存管理 Block的循环引用 一、Block介绍 1...

  • block的内存管理

    block的内存默认放在栈中,(开发人员不需要管理block内存),block所引用的对象的retainCount...

  • block的一些注意事项

    Block的使用注意: block的内存管理(注意循环引用,默认在栈中(不需要内存管理),通过copy就在在堆中,...

网友评论

      本文标题:Block内存管理

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