美文网首页面试相关iOS Developer
Block学习笔记2-Block实质

Block学习笔记2-Block实质

作者: Shirley_y | 来源:发表于2017-02-18 10:58 被阅读299次

参考书籍:《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函数指针调用函数。

相关文章

  • Block学习笔记2-Block实质

    参考书籍:《Effective Objective-C 2.0》 《Objective-C高级编程 iOS与OS ...

  • 《OC高级编程》之 Blocks(二)

    Block 的实现 Block 的实质     Block 实质上是 Object-C 对象     所谓截获自动...

  • Block实质

    PersonalBlog首发: http://lanjiying.allenqin.com/2018/04/11/...

  • block实质

    实际上block就是这俩玩意了 我们来举个栗子看看 使用clang指令clang -rewrite-objc ma...

  • block实质

    block实质是:封装了函数及其执行上下文的对象 block调用的本质是:函数的调用

  • block概念

    block的实质: block实质是oc对闭包的对象实现,简单点来说 block就算是对象。 block的书写方式...

  • 2019年年初iOS招人心得笔记 答案 (三)

    中级Block 1、block的实质是什么?一共有几种block?都是什么情况下生成的? block的实质是什么?...

  • 2019 iOS 面试 -中级篇之 Block

    1. block的实质是什么?一共有几种block?都是什么情况下生成的? block的实质是什么? block本...

  • Block探究

    block的实质是什么?一共有几种block?都是什么情况下生成的? block的实质是什么? block本质上也...

  • block的实质

    1.什么是block block是将函数及其执行上下文封装起来的对象,是一段代码块,是一个结构体,里面有isa指针...

网友评论

本文标题:Block学习笔记2-Block实质

本文链接:https://www.haomeiwen.com/subject/lfbzittx.html