Block学习笔记2-Block实质

参考书籍:《Effective Objective-C 2.0》 《Objective-C高级编程 iOS与OS X多线程和内存管理》
根据书中所说,Block是“带有自动变量值的匿名函数”,下面算是我的读书笔记,附上由clang编译出来的过程代码来理解Block的实质。
首先介绍下clang,Clang是一个[C语言]、[Objective-C]、C++语言的轻量级编译器。---百度百科

1.相关clang命令

可能用到的关于clang的指令如下:
cd到main目录下,执行clang -rewrite-objc main.m指令,可以将OC源码转换成C语言源代码,但要注意这里转换出来的C源码并不是最终程序执行的源码,只是过程代码,所以仅便于我们从更加底层的了解OC源码。源码无错且执行完毕后同级目录下便会出现main.cpp文件。

1.若要指定模拟器环境下运行:
首先可执行xcodebuild -showsdks查看本地装有的SDK
然后执行xcrun -sdk iphonesimulatorx.x clang -rewrite-objc main.m(x.x即为本机安装的模拟器版本)
2.若指定真机运行
xcrun -sdk iphoneosx.x clang -rewrite-objc main.m
3.若代码中import了第三方的SDK,可以通过下列命令关闭
xcrun -sdk iphonesimulator10.0 clang -rewrite-objc -F /Users/Desktop main.m
注意,在mac系统下,无需先建工程再执行源码转化,在任意目录先新建一个m文件即可转换。

2.Block源码

先举一个简单的block,方便查看Block的结构。

OC源码:
#import <Foundation/Foundation.h>
int main(int argc, char * argv[]) {
      @autoreleasepool {  
          void (^aBlock)() = ^{
                                  NSLog(@"Hello world !");
                               };
          aBlock();
      }  
    return 0;
}

转换后的相关C源码如下:(转换出来的源码虽然有九万多行,但大部分是因为我导入了Foundation框架,以下只列出与main有关的部分源码)

Block c源码截图.png

虽然书中已经写的很详细了,但我这里重新理一遍理解的思路,一方面是便于自己梳理要点便于记忆,另一方面有关于书中有些疑问,在这里记下来,方便日后交流与回顾。
下面根据上图中的标号顺序来理解这段转换成C源码的实现原理:
1.先来看看一眼就能认出的block内容部分,在OC中添加的block内容为^{NSLog(@"Hello world !");};在标注1的地方正好能看到熟悉的NSLog,所以可以看出静态函数__main_block_func_0即对应OC中block中执行的函数部分。

2.接着来看main_block_func_0中传递的参数为 main_block_impl_0结构体类型的 cself指针,这里cself就相当于self(不做拓展介绍,更多的细节请自己查阅更加底层的资料)。然后来具体看__main_block_impl_0结构体,在标注2的地方即为这个结构体的成员变量与构造函数。
这个结构体包含两种变量与一个构造函数:

  • __block_impl impl
  • __main_block_desc_0* Desc;
  • 构造函数__main_block_impl_0

前两种结构体变量稍后讲述,先看一下构造函数main_block_impl_0中所传递的参数为void *fp,struct __main_block_desc_0 *desc, int flags=0
其中fp即为指向block要实现的函数指针,desc为block的相关描述信息,直接赋给Desc变量,最后是带默认值的flags变量。

3.先来看__main_block_impl_0结构体:

  • isa:指向实例对象,正好表明Block也跟一般的OC对象类似,拥有isa指针,共有三种block类型:_NSConcreteStackBlock、_NSConcreteGlobalBlock、_NSConcreteMallocBlock
  • Flags :按位承载 block 的附加信息;
  • Reserved:保留变量;
  • FuncPtr: 函数指针,指向 Block 要执行的函数

4.再来看__main_block_desc_0:block 的相关描述信息结构体

  • reserved:结构体信息保留字段
  • Block_size:结构体大小
  • 结构体类型变量: __main_block_desc_0_DATA

5.main函数部分
void (*aBlock)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
这句能猜到就对应着void (^aBlock)() = ^{NSLog(@"Hello world !");};
将其强制转化等操作去掉后,就仅剩下了*aBlock = &__main_block_impl_0;就可以看出这就是一个简单的指针赋值,将main_block_impl_0结构体赋值给aBlock指针。我的理解为通过构造函数构造出一个main_block_impl_0结构体并赋给了一个指针,这个即为block的c层面上的理解。
6.最后看main中的调用block部分:
OC: aBlock(); C: ((void (*)(__block_impl *))((__block_impl *)aBlock)->FuncPtr)((__block_impl *)aBlock);
这句代码可简化为*aBlock->impl.FuncPtr,即通过aBlock变量中的impl的FuncPtr函数指针调用函数。

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

推荐阅读更多精彩内容