OC底层 - block捕获变量

本文介绍了OC语言中block对不同变量的捕获情况。block是OC对象,代码块封装在函数中。当block使用局部变量(自动变量)时会捕获变量值;使用局部静态变量时捕获其地址;对全局变量不捕获,直接调用;会捕获self的地址;调用对象成员变量时,通过捕获的self来调用。

block是oc语言的一种代码块, 底层实现为oc对象, 代码块封装在一个函数中, 函数作为该oc对象的一个变量, 调用时, 直接调用该函数;

什么情况下block会捕获变量呢?

局部变量(自动变量)

如果block中使用了方法中的局部变量, 如下:

-(void)test
{
    int age = 10;
    void(^block1)(void) ^{
        NSLog(@"%ld",age);
    };
}

因为局部变量(自动变量)在test方法结束的时候会被自动释放, 但是block可能此时还没调用, 这时候block就需要将age变量据为己有, 直接捕获变量age, 作为自己的一个变量;

当变量被捕获时, 即使修改该变量, block内部的age也不会改变, 因为外部的age与block内部的age已经不是同一个age;

-(void)test
{
    int age = 10;
    void(^block1)(void) ^{
        NSLog(@"%ld",age);
    };
    age = 20;
    block1();
}

局部静态变量

因为静态变量并不会因为test方法的结束而释放, 这时候也会捕获静态局部变量age, 但是这时候是捕获的age的地址, 外部修改age, 会直接修改block中的内容;

-(void)test
{
    static int age = 10;
    void(^block1)(void) ^{
        NSLog(@"%ld",age);
    };
    age = 20;
    block1();
}

全局变量

因为全局变量的声明周期伴随着对象的声明周期, 所以block并不会捕获age, 而是直接调用外部的age;

int age = 10;
static int age2 = 10;
-(void)test
{
    
    void(^block1)(void) ^{
        NSLog(@"%ld",age);
    };
    age = 20;
    block1();
}

self

oc编程的实现原理为, 方法内部有两个默认的变量, 一个是self,当前对象的指针 , 一个是sel, 当前方法的地址, 所以self是方法test的内部局部变量, 所以self会被捕获, 捕获的是地址;

-(void)test
{
    
    void(^block1)(void) ^{
        NSLog(@"%@",self);
    };
    block1();
}

对象成员变量

对于成员变量而言, 在block中调用_name, 其实是self->_name 这样子调用的, self是局部变量, 会被捕获, block内部根据捕获的self调用_name;

对象的成员变量
_name;
-(void)test
{
    
    void(^block1)(void) ^{
        NSLog(@"%@",_name);
    };
    block1();
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值