iOS底层学习|block-2-捕获

55 阅读1分钟

变量捕获capture

局部变量
-(void)testBlock {
    int age = 10;
    void(^blcok)(void) = ^(void){
        NSLog(@"block - %d",age);
    };
    age = 20;
    blcok();
}
  • 打印
10

根据大神贴出的源码,其实底层C++代码就是将age作为参数传递,仅仅传递的是age的值,所以是值传递

__block修饰
-(void)testBlock {
    __block int age = 10;
    void(^blcok)(void) = ^(void){
        NSLog(@"block - %d",age);
    };
    age = 20;
    blcok();
}
  • 打印
20

C++源码中,是以&age形式传递参数的,因此是地址传递

auto __block static
-(void)testBlock {
    auto int weight = 1;
    __block int age = 2;
    static int height = 3;
    void(^blcok)(void) = ^(void){
        NSLog(@"block: weight - %d , age - %d, height - %d",weight,age,height);
    };
    weight = 10;
    age = 20;
    height = 30;
    blcok();
}
  • 打印
block: weight - 1 , age - 20, height - 30

auto 默认的局部变量修饰关键字 局部变量是以值作为参数传递的,__block和static修饰的变量是以指针形式作为参数传递的

全局变量
int ageGlobal = 1;
static int heightGlobal = 2;

-(void)testBlock {
    
    void(^blcok)(void) = ^(void){
        NSLog(@"block: ageGlobal - %d , heightGlobal - %d",ageGlobal,heightGlobal);
    };
    ageGlobal = 10;
    heightGlobal = 20;
    blcok();
}
  • 打印
block: ageGlobal - 10 , heightGlobal - 20

全局变量在C++底层代码中都是直接访问的,并不是以值传递或者指针传递的

特殊情形
-(void)testBlock {
    void(^blcok)(void) = ^(void){
        NSLog(@"%@",self);
    };
    blcok();
}

如上代码,self也是变量捕获,如下代码oc中每个函数都有默认的两个参数,既然作为参数也就是局部变量,因此也就会被捕获

-(void)testBlock(self,(SEL)sel) {
}

总结

  1. 局部变量会被捕获,是以值作为参数传递的
  2. 全局变量不会被捕获,是以直接访问的形式获取值的
  3. static和__block 修饰的都是指针形式传递的