美文网首页
Block声明时的内存位置和copy后的内存位置

Block声明时的内存位置和copy后的内存位置

作者: 传说中的汽水枪 | 来源:发表于2019-01-18 10:54 被阅读8次

    Block在引用不同类型的外部变量的时候,它的位置也是不同的。

    先看这样的一段代码:

    NSInteger globalVariable = 1;
    
    @interface RXBlockChangeOverTimeObject()
    @property (nonatomic, copy) NSInteger(^block)(NSInteger);
    @property (nonatomic, assign) NSInteger instanceVariable;
    @end
    
    @implementation RXBlockChangeOverTimeObject
    - (void)test
    {
        // 定义几种类型的变量
        self.instanceVariable = 10;
        NSInteger localVariable = 100;
        static NSInteger staticLocalVariable = 99;
        __block NSInteger blockVariable = 1000;
        // 定义分别使用类型变量的block
        NSInteger (^block_noVariable)(NSInteger) = ^(NSInteger m) {
            return m;
        };
    }
    

    几种变量的类型

    • 全局变量,例如:globalVariable
    • 实例变量,例如:self.instanceVariable
    • 本地变量,例如:localVariable
    • 本地静态变量,例如:staticLocalVariable
    • __block变量,例如:blockVariable
    • 入参,例如:NSInteger m

    输出block信息:

    + (void)printBlockWithPrefix:(NSString *)prefix block:(id)block
    {
        NSLog(@"%@, class:%@, address:%p", prefix, [block class], block);
    }
    

    ARC 环境下的测试:

    - (void)test
    {
        NSLog(@"--------RXBlockChangeOverTimeObject--------");
        // 定义几种类型的变量
        self.instanceVariable = 10;
        NSInteger localVariable = 100;
        static NSInteger staticLocalVariable = 99;
        __block NSInteger blockVariable = 1000;
        
        // 定义分别使用类型变量的block
        NSInteger (^block_noVariable)(NSInteger) = ^(NSInteger m) {
            return m;
        };
        NSInteger (^block_globalVariable)(NSInteger) = ^(NSInteger m) {
            return m + globalVariable;
        };
        __weak typeof(self) weakSelf = self;
        NSInteger (^block_instanceVariable)(NSInteger) = ^(NSInteger m) {
            return m + weakSelf.instanceVariable;
        };
        NSInteger (^block_localVariable)(NSInteger) = ^(NSInteger m) {
            return m + localVariable;
        };
        NSInteger (^block_staticLocalVariable)(NSInteger) = ^(NSInteger m) {
            return m + staticLocalVariable;
        };
        NSInteger (^block_blockVariable)(NSInteger) = ^(NSInteger m) {
            blockVariable++;
            return m + blockVariable;
        };
        NSInteger (^block_composedVarialbe)(NSInteger) = ^(NSInteger m) {
            return m + localVariable + staticLocalVariable;
        };
        
        // 输出定义好的block变量
        [RXPrintUtil printBlockWithPrefix:@"block_noVariable" block:block_noVariable];
        [RXPrintUtil printBlockWithPrefix:@"block_globalVariable" block:block_globalVariable];
        [RXPrintUtil printBlockWithPrefix:@"block_instanceVariable" block:block_instanceVariable];
        [RXPrintUtil printBlockWithPrefix:@"block_localVariable" block:block_localVariable];
        [RXPrintUtil printBlockWithPrefix:@"block_staticLocalVariable" block:block_staticLocalVariable];
        [RXPrintUtil printBlockWithPrefix:@"block_blockVariable" block:block_blockVariable];
        [RXPrintUtil printBlockWithPrefix:@"block_composedVarialbe" block:block_composedVarialbe];
        
        // 分别设置block
        self.block = block_noVariable;
        [RXPrintUtil printBlockWithPrefix:@"self block_noVariable" block:self.block];
        
        self.block = block_globalVariable;
        [RXPrintUtil printBlockWithPrefix:@"self block_globalVariable" block:self.block];
        
        self.block = block_instanceVariable;
        [RXPrintUtil printBlockWithPrefix:@"self block_instanceVariable" block:self.block];
        
        self.block = block_localVariable;
        [RXPrintUtil printBlockWithPrefix:@"self block_localVariable" block:self.block];
        
        self.block = block_staticLocalVariable;
        [RXPrintUtil printBlockWithPrefix:@"self block_staticLocalVariable" block:self.block];
        
        self.block = block_blockVariable;
        [RXPrintUtil printBlockWithPrefix:@"self block_blockVariable" block:self.block];
        
        self.block = block_composedVarialbe;
        [RXPrintUtil printBlockWithPrefix:@"self block_composedVarialbe" block:self.block];
    }
    

    运行结果:

    --------RXBlockChangeOverTimeObject--------
    block_noVariable, class:__NSGlobalBlock__, address:0x10753ad40
    block_globalVariable, class:__NSGlobalBlock__, address:0x10753ad80
    block_instanceVariable, class:__NSMallocBlock__, address:0x60000024fc60
    block_localVariable, class:__NSMallocBlock__, address:0x6000002502c0
    block_staticLocalVariable, class:__NSGlobalBlock__, address:0x10753ae10
    block_blockVariable, class:__NSMallocBlock__, address:0x600000250740
    block_composedVarialbe, class:__NSMallocBlock__, address:0x600000253680
    self block_noVariable, class:__NSGlobalBlock__, address:0x10753ad40
    self block_globalVariable, class:__NSGlobalBlock__, address:0x10753ad80
    self block_instanceVariable, class:__NSMallocBlock__, address:0x60000024fc60
    self block_localVariable, class:__NSMallocBlock__, address:0x6000002502c0
    self block_staticLocalVariable, class:__NSGlobalBlock__, address:0x10753ae10
    self block_blockVariable, class:__NSMallocBlock__, address:0x600000250740
    self block_composedVarialbe, class:__NSMallocBlock__, address:0x600000253680
    RXBlockChangeOverTimeMRCObject dealloc
    

    MRC环境下的测试:

    #include <malloc/malloc.h>
    - (void)test
    {
        NSLog(@"--------RXBlockChangeOverTimeMRCObject--------");
        // 这一部分的测试代码就跟ARC测试代码一致,只不过如下的不一样:
        // MRC解决循环引用
        __block __typeof(self) weakSelf = self;
        NSInteger (^block_instanceVariable)(NSInteger) = ^(NSInteger m) {
            if (malloc_zone_from_ptr(weakSelf)) {
                return m + weakSelf.instanceVariable;
            } else {
                return m;
            }
        };
    }
    - (void)dealloc
    {
        [super dealloc];
        NSLog(@"RXBlockChangeOverTimeMRCObject dealloc");
    }
    

    运行结果:

    --------RXBlockChangeOverTimeMRCObject--------
    block_noVariable, class:__NSGlobalBlock__, address:0x107537ac0
    block_globalVariable, class:__NSGlobalBlock__, address:0x107537b00
    block_instanceVariable, class:__NSStackBlock__, address:0x7ffee8c656e8
    block_localVariable, class:__NSStackBlock__, address:0x7ffee8c656b8
    block_staticLocalVariable, class:__NSGlobalBlock__, address:0x107537b90
    block_blockVariable, class:__NSStackBlock__, address:0x7ffee8c65680
    block_composedVarialbe, class:__NSStackBlock__, address:0x7ffee4dc4650
    self block_noVariable, class:__NSGlobalBlock__, address:0x107537ac0
    self block_globalVariable, class:__NSGlobalBlock__, address:0x107537b00
    self block_instanceVariable, class:__NSMallocBlock__, address:0x600000253680
    self block_localVariable, class:__NSMallocBlock__, address:0x6000002502c0
    self block_staticLocalVariable, class:__NSGlobalBlock__, address:0x107537b90
    self block_blockVariable, class:__NSMallocBlock__, address:0x6000002502c0
    self block_composedVarialbe, class:__NSMallocBlock__, address:0x60400025e900
    RXBlockChangeOverTimeMRCObject dealloc
    
    1. 可以把RXBlockChangeOverTimeMRCObject.m文件的compiler flsgs设置为:fno-objc-arc来表明此文件是MRC的。
    2. 也可以在MRC下使用__weak:
      image.png
      默认是No,可以改成Yes

    结论

    image.png

    相关文章

      网友评论

          本文标题:Block声明时的内存位置和copy后的内存位置

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