block详解

block本质:

每个OC对象内部都有isa指针,block也不例外;block其实就是封装函数调用,以及函数调用环境的OC对象。

block底层结构:

block底层结构

block的类型:

内存几大区域

常见的有以下三种block:

NSMallocBlock :存放在堆区的 Block

NSStackBlock  : 存放在栈区的 Block

NSGlobalBlock : 存放在全局区的 Block

当block 没有截获外部变量、截获全局变量的都是属于全局区的 Block,即 GlobalBlock;其余的都是栈区的 Block,即 StackBlock;

对于全局区的 Block,是不存在作用域的问题,但是栈区 Block 不同,在作用域结束后就会 pop 出栈,__block 变量也是在栈区的,同理作用域结束也会 pop 出栈。

为了解决作用域的问题,block 提供了 copy 函数,将 block 从栈复制到堆上,在 MRC 环境下需要我们自己调用 block_copy  函数,这里就是为什么 MRC 下,我们为什么需要用 copy 来修饰 Block 的原因。

MRC情况下:

MRC的情况下

ARC情况下:

编译器会根据情况自动添加copy,将栈上的block拷贝到堆上,比如以下情况:

1、block作为函数返回值

2、block赋值给__strong指针

3、block作为Cocoa API中的方法名含有usingBlock的方法参数时

4、block作为GCD API参数时

每一种类型的block调用copy后的结果如下:

使用copy结果示意图

block捕获机制:

block捕获机制
捕获auto、static局部变量

因为auto的局部变量在离开作用域会销毁,所以block内部使用值传递的方式捕获到,因此在block内部不能更改auto变量的值,像int因为值是直接存储在变量内存里面,所以不能更改;而static因为是指针传递所有能更改。

更改mArr内容
更改mArr指针地址

因为NSMutableArray 变量里面其实存的是指针地址,所以直接操作指针里面的内容是可以的,如果直接更改变量存储的指针地址就不行。

如果是全局变量不会捕获,不管在哪个函数都能直接访问;局部变量因为作用域的问题,可能存在跨函数访问所以会捕获。

如果block中引用实例变量(比如说name)不管是通过self.name还是_name,block都会捕获self对象.因为方法的调用默认传递两个参数(self,sel)所以self为局部变量,block引用局部变量都会捕获。

既然block对局部auto变量是值传递,那么如果想要在block内部修改auto变量怎么修改?

如果block外部变量是auto变量可以使用__block;如果是static静态变量 或者全局变量,则不需要修饰也能更改。(参考捕获机制)

原理:在ARC环境下,编译器会尽可能给我们自动添加 copy 操作。使用copy从栈复制到堆上,__block 修饰的变量也会从栈复制到堆上;为了结构体 __block 变量无论在栈上还是在堆上,都可以正确的访问变量,我们需要 forwarding 指针forwarding指针的作用:保证当我们将 Block 从栈拷贝到堆中,修改的变量都是同一份。

forwarding原理:在 Block 从栈复制到堆上的时候,原本栈上结构体的 forwarding 指针,会改变指向,直接指向堆上的结构体。这样子就可以保证之后我们都是访问同一个结构体中的变量,这里就是为什么 __block 修饰的变量,在 Block 内部中可以修改的原因了。

forwarding指针

__block底层实现:

当__block变量在栈上时:

并不会对指向的对象产生强引用。

当__block变量被copy到堆上时:

copy函数内会调用_Block_object_assign函数;_Block_object_assign函数会根据auto变量(对象类型)的修饰符(__strong,__weak, __unsafe_unretained)做出相应的操作形成强、弱引用;

当__block变量被从堆上移除时:

会调用Block内部的dispose函数 dispose函数内部会调用_Block_object_dispose函数 _Block_object_dispose函数会自动释放引用的auto变量,类似于release。

block引起循环引用场景:

当 A 持有 B,B 又持有 A,这个时候就会出现循环引用。Block 对于外部变量都会追加到结构体中,所以在实现 Block 时候需要注意这个问题。

解决方案:

ARC 环境一般我们用 __weak 来打破,MRC 环境的话,我们可以使用 __block 来打破循环引用。

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

推荐阅读更多精彩内容

  • 目录1.Block 的基本使用2.Block 的底层数据结构3.Block 的变量捕获机制3.1 auto 类型的...
    师大小海腾阅读 1,000评论 0 9
  • iOS开发---Block详解 Block的基础 什么是Blocks? 用一句话来描述:带有自动变量的匿名函数(是...
    祀梦_阅读 1,002评论 0 6
  • 第一部分:Block本质 Q:什么是Block,Block的本质是什么? block本质上也是一个OC对象,它内部...
    sheldon_龙阅读 555评论 0 0
  • 1.明白如何定义block类型 定义Block类型: typedef 返回值类型 Block名字 参数 block...
    哈库呐玛塔塔__阅读 634评论 0 0
  • 一、Block本质 Block是“带有自动变量值的匿名函数”。 所谓的匿名函数就是不带有名称的函数 但它究竟是什么...
    枫叶情结阅读 489评论 1 0