OC底层-Block本质(二、变量捕获)

JackMayx 2020/6/29 23:27:20

前言 为了保证block内部能够正常访问外部的变量,block有一个变量捕获机制。 局部变量 auto 变量(默认的auto) 在上一篇代码中我们已经了解过block对age变量的捕获。 auto自动变量,离开作用域就销毁,局部变量前面自动添加auto关键字。自动变量会捕获到block内部,也就…

前言

为了保证block内部能够正常访问外部的变量,block有一个变量捕获机制。

局部变量

auto 变量(默认的auto)

在上一篇代码中我们已经了解过block对age变量的捕获。 auto自动变量,离开作用域就销毁,局部变量前面自动添加auto关键字。自动变量会捕获到block内部,也就是说block内部会专门新增加一个参数来存储变量的值。 auto只存在于局部变量中,访问方式为值传递,通过上述对age参数的解释我们也可以确定确实是值传递。

static变量

static 修饰的变量为指针传递,同样会被block捕获。

接下来分别添加auto修饰的局部变量和static修饰的局部变量,重看源码来看一下他们之间的差别:

auto int a = 10;
static int b = 10;
void(^block)(void) = ^{
     NSLog(@"hello, a = %d, b = %d", a,b);
     ///打印 hello, a = 10, b = 20
};
a = 20;
b = 20;
block();
复制代码

通过命令行我们查看源代码:

从上述源码中可以看出,a,b两个变量都有捕获到block内部。但是a传入的是值,而b传入的则是地址。

为什么两种变量会有这种差异呢,因为自动变量可能会销毁,block在执行的时候有可能自动变量已经被销毁了,那么此时如果再去访问被销毁的地址肯定会发生坏内存访问,因此对于自动变量一定是值传递而不可能是指针传递了。而静态变量不会被销毁,所以完全可以传递地址。而因为传递的是值得地址,所以在block调用之前修改地址中保存的值,block中的地址是不会变得。所以值会随之改变。

全局变量

我们以同样的方式来研究下block是否捕获全局变量

int a = 10;
static int b = 10;
int main(int argc, const char * argv[]) {
    @autoreleasepool {

        void(^block)(void) = ^{
            NSLog(@"hello, a = %d, b = %d", a,b);
            /// 打印hello, a = 20, b = 20
        };
        a = 20;
        b = 20;
        block();
    }
    return 0;
}
复制代码

源代码:

通过上述代码可以发现,__main_block_imp_0并没有添加任何变量,因此block不需要捕获全局变量,因为全局变量无论在哪里都可以访问。 局部变量因为跨函数访问所以需要捕获,全局变量在哪里都可以访问 ,所以不用捕获。 所以用下面这张图做个总结:

总结:局部变量都会被block捕获,自动变量是值捕获,静态变量为地址捕获。全局变量则不会被block捕获

疑问思考:以下代码中block是否会捕获变量呢?

#import "Person.h"
@implementation Person
- (void)test
{
    void(^block)(void) = ^{
        NSLog(@"%@",self);
    };
    block();
}
- (instancetype)initWithName:(NSString *)name
{
    if (self = [super init]) {
        self.name = name;
    }
    return self;
}

@end

复制代码
随时随地学软件编程-关注百度小程序和微信小程序
关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。
本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。
[OC底层-Block本质(二、变量捕获)]http://www.zyiz.net/tech/detail-141531.html

上一篇:SwiftUI之如何监听Dismiss手势

下一篇:SwiftUI动画(1)之Animatable

赞(0)

共有 条评论 网友评论

验证码: 看不清楚?
    关注微信小程序
    程序员编程王-随时随地学编程

    扫描二维码或查找【程序员编程王】

    可以随时随地学编程啦!

    技术文章导航 更多>
    扫一扫关注最新编程教程