iOS Block原理总结(一)

iOS Block原理总结(一)

IOS小彩虹2021-07-25 0:26:08180A+A-

目录

1. Block的本质

2. Block的底层结构

3.Block对不同类型变量的捕获


Block的本质

block是一个OC对象,本质是一个结构体,里面存放了上下文变量和指向函数体的函数指针。

  • 为什么说block是一个OC对象:
#import "BlockMemoryViewController.h"
#import <objc/runtime.h>
@interface BlockMemoryViewController ()
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    int i = 10;
    void (^tmpBlock)(void) = ^{
        NSLog(@"i = %d", i);
    };
    Class blockClass = object_getClass(tmpBlock);
    while (blockClass) {
        NSLog(@"class = %@", blockClass);
        blockClass = class_getSuperclass(blockClass);
    }
}

通过rutime的object_getClass查找父类的方法,遍历查询,打印结果:NSGlobalBlock -> NSBlock -> NSObject,即它的根类是NSObject,所以说block是一个OC对象(当然内部结构体包含isa指针也能看出来)

Block的底层结构

我们写一个block,转换成C++代码来看看里面的结构:

截屏2021-03-24 下午2.46.24.png

上面是一个带自动变量block,主要结构如下图: 截屏2021-03-24 下午5.24.10.png

通过上面的图示关系,详细看看每个部分的代码及作用:

1. main_block_impl_0结构体:

包含以下内容:
a. __block_impl类型的结构体里面存放block信息、isa、函数指针;
b. __main_block_desc_0 结构体指针,主要描述block的大小等信息;
c. age 自动生成一个变量用于保存外面传进来变量,即捕获变量;
d. __main_block_impl_0(x,x,x,x),初始化方法给上面的参数赋值.

2.函数实现 :
__main_block_func_0()函数,参数传入main_block_impl_0,即可以取出main_block_impl_0里面的信息,完成block括号{}的内容。

截屏2021-03-24 下午3.21.43.png

main函数block代码转换: 截屏2021-03-24 下午3.19.30.png

这里我们就能很清晰的看到底层具体是怎么做了:

  1. 通过main_block_impl_0构造方法传入参数:函数指针__main_block_func_0 、block信息、截获的变量age并赋值,得到main_block_impl_0结构体
  2. 调用block:main_block_impl_0转换为block_impl类型并调用block_impl中的函数指针FuncPtr执行__main_block_func_0函数,并将main_block_impl_0传入取出里面生成的变量age,完成NSLog方法。

一个自动变量的block从如何生成、如何截获变量、如何调用,通过上面的分析相信已经有了很清晰的了解。

不同类型变量的截获

上面分析了Block的底层实现顺便看了一下局部变量的截获情况 下面我们具体分析一下不通类型变量的截获情况:

  1. 全局变量:globalValue
  2. 全局静态变量:staticGlobal
  3. 局部变量:autoValue
  4. 局部静态变量:staticValue
  5. 成员变量:label

截屏2021-03-24 下午5.06.06.png

为了方便查看这里展示主要部分:

截屏2021-03-24 下午5.10.41.png

通过上面的源码我们可以得出以下结论:

  1. 全局变量、全局静态变量(globalValue、staticGlobal)并没有被截获,而是直接使用;
  2. 局部变量被(autoValue),被截获且Block内部生成了一个变量来保存它的值;
  3. 局部静态变量(staticValue)捕获了变量的地址,生成一个指针保存;
  4. 成员变量(label)捕获了self;

Block对不同类型变量的捕获总结:
1.任何类型全局变量都不会被捕获,因为全局变量任何位置都能访问,所以Block可以直接获取即可。
2. 局部变量被捕获且Block内部生成了一个变量来保存它的值,因为局部变量出了作用域则被释放,而Block一般都是延迟调用,所以生成一个变量保存它,避免后续访问的时候被释放了;
3. 局部静态变量会被捕获地址,因为作用域的原因,Block内部无法像访问全局变量一样访问它,而且局部静态变量一直会在内存中不会被释放,所以直接捕获它的地址,生成一个指针保存和取值;
4. 成员变量会被捕获self,通过捕获self发送消息来实现成员变量的对象方法。

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1
本网站由 提供CDN/云存储服务

联系我们