Block变量捕获详解(一)

  • 什么是Block变量捕获
    block变量捕获就是在block内部创建一个变量来存放外部变量
  • 什么是值捕获
    block将外部变量的值存放到了内部新创建的一个变量中
  • 什么是指针捕获
    block将外部变量的指针存放到了内部新创建的一个变量中
  • 会对全局变量捕获吗
    不会对全局变量捕获,只会对局部变量进行捕获

问题1

    int age = 10;
    void (^captureBlock)(void) = ^{
        NSLog(@"age is %d",age);
    };
    age = 20;
    captureBlock();

问题:打印出来age是多少
正确答案:10
这是一道关于block的变量捕获的问题,如果对block变量捕获不是很明白的话,很容易说出age是20的错误答案。在block还没调用时,block已经对age的值捕获了,并在block内部生成了一个age变量,将外部age的值赋值了自己生成的age,这时block内部的age的值已经跟外部的没有关联了,所以当外部值改变时并不会影响到内部的值。这种情况称为block的值捕获。
在1-1可以看到,在内部已经另外生成了一个age。


1-1.png

问题2

    int age = 10;
    static int height = 10;
    void (^captureBlock)(void) = ^{
        NSLog(@"age is %d,height is %d",age,height);
    };
    age = 20;
    height = 20;
    captureBlock();

问题:打印的age和height分别是多少
答案:age:10 height:20
这个问题对比上个问题多了个height变量,但是这个变量跟age是有区别的,height是static变量。在运行时block对static局部变量的捕获是指针捕获,block中存放的是外部height变量的指针,当外部的值改变时内部值也会跟着改变。从2-1可以看出,在编译以后main函数block中age是值传递,height是指针传递。2-2中block内部也分别生成了int age和int *height用来接收外部的值。


2-1.png

2-2.png
为什么局部变量age是值传递而static修饰的局部变量是指针传递呢?
  • 因为局部变量age在离开作用域时(就是离开大括号时)就会被释放,如果block是个全局,在其他作用域调用时,如果age是指针传递(保存的是指针),这时block去调用age时,age已经离开作用域被释放了,内存已经不存在了,这时就会报错,存在访问野指针的情况。所以对于局部变量非static修饰时,block就会值捕获。
  • static修饰的局部变量其内存会一直存在,不会因为离开作用域而被释放,所以当全局block在其他作用域调用时不会报错。
//定义block类型
void(^block)(void);

void test(){
    int age = 10;
    static int height = 20;
//在block内部访问 age , height
    block = ^{
        NSLog(@"age is %d, height is %d",age,height);
    };
    age = 20;
    height = 20;
}

//在main函数中调用
int main(int argc, const char * argv[]) {
        test();
 //test调用后,age变量就会自动销毁,如果block内部是保留age变量的指针,那么我们在调用block()时,就出现访问野指针
        block();
}

问题3

先声明两个全局变量age_和height_

int age_;
int height_;
    age_ = 10;
    height_ = 10;
    void (^captureBlock)(void) = ^{
        NSLog(@"age is %d,height is %d",age_,height_);
    };
    age_ = 20;
    height_ = 20;
    captureBlock();

问题:打印的age和height分别是多少
答案:age:20 height:20
这个问题和前面两个问题又有所区别,这次age和height是一个全局变量,这次打印20的答案不是因为block的指针捕获导致的。从3-1中可以看到,在编译以后block中并没有生成一个age和height变量,所以block并没有对age和height两个变量进行捕获。因为age和height是全局变量,在任何的作用域下都是能调用的,所以block不会多此一举对其进行捕获,在内部直接访问就可以。


3-1.png

block变量捕获总结

  1. block只会对局部变量捕获不会对全局变量捕获
    因为局部变量只能在本作用域内才能被调用,block为了能在其他作用域内调用只能对其捕获。全局变量在任何地方都能被调用,所以不需要对其捕获。
  2. 对static局部变量是指针捕获,auto局部变量是值捕获
    在局部变量中不是static变量的默认为auto变量

Block的三种类型(二)
Block对象捕获(三)
__block修饰符(四)
Block循环引用(五)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容