iOS基础 - Block变量截获(总结)

一、局部变量截获是 “值截获”

    NSInteger number = 30;
    
    NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){
        
        return n + number;
    };
    
    num = 5;
    
    NSLog(@"%zd", block(10));

这里输出结果是 40,而不是 15,原因是对局部变量 number 的截获是 “值截获”。在 block 里面修改 number,是无效的,并且编译会报错。

    NSMutableArray *testArray = [NSMutableArray arrayWithObjects:@"zhang",@"li", nil];
    
    void(^block)(void) = ^{
        
        NSLog(@"%@",testArray);//局部变量
            
        [testArray addObject:@"qian"];
    };
    
    [testArray addObject:@"wang"];
    
    testArray = nil;
    
    block();

打印结果为 zhang, li, wang

局部对象变量也是 “值截获”,截获的是值,而不是指针,在外部将其置为 nil,对 block 没有影响。

但是该对象调用方法会影响结果(如NSMutableArray 的 addObject,NSMutableString 的 appendString)。

二、局部静态变量截获是 “指针截获”

   static NSInteger number = 30;
    
    NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){
        
        return n + number;
    };
    
    number = 5;
    
    NSLog(@"%zd", block(10));

输出结果是 15,说明 number = 5 的修改是有效的,即是 “指针截获”。

同时,在 block 里修改变量 number ,也是有效的(如:在 block 里面将 number 修改为 50,输出结果为 60)。

三、全局变量 与 静态全局变量,是 “不截获, 直接取值”

用 clang 编译一下

static NSInteger number3 = 100;
NSInteger number4 = 1000;

- (void)blockTest
{
    NSInteger number = 10;
    static NSInteger number2 = 1;
    __block NSInteger number5 = 10000;
    
    void(^block)(void) = ^{
        
        NSLog(@"%zd",number); //局部变量
        NSLog(@"%zd",number2); //静态变量
        NSLog(@"%zd",number3); //全局变量
        NSLog(@"%zd",number4); //全局静态变量
        NSLog(@"%zd",number5); //__block修饰变量
    };

    number = 50;
    number2 = 5;
    number3 = 500;
    number4 = 5000;
    number5 = 50000;

    block();
}

输出结果为 : 10    5    500    5000    50000

编译后

struct __Block__blockTest_block_impl_0 {
    struct __block_impl impl;
    struct __Block__blockTest_block_desc_0* Desc;
    NSInteger number;//局部变量
    NSInteger *number2;//静态变量
    __Block_byref_number5_0 *number5; // by ref//__block修饰变量
    __Block__blockTest_block_impl_0(void *fp, struct __Block__blockTest_block_desc_0 *desc, NSInteger _number, 
NSInteger *_number2, __Block_byref_number5_0 *_number5, int flags=0) : number(_number), number2(_number2), number5(_number5->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};

从 “&_NSConcreteStackBlock” 可以看出,这是一个栈block。局部变量被编译成值形式,而静态变量被编译成指针形式,全局变量并未截获。而__block 修饰的变量也是以指针形式截获的,并且生成了一个新的对象:
 

struct __Block_byref_number5_0 {
    void *__isa;
    __Block_byref_number5_0 *__forwarding;
    int __flags;
    int __size;
    NSInteger number5;
};

对于局部变量,如果需要在 block 内部进行赋值操作,需要给局部变量添加__block 修饰符,而对于全局变量、静态变量是不需要添加__block 修饰符的。如果 block 内部访问了 self 或者 self 的成员变量,block 会截获 self。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HiccupTang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值