Block的相关问题

(1)block的概念:
block 是将函数和执行上下文 封装起来的对象。block调用-->函数调用。

block变量其实解释一个函数指针。

block 调用就是函数调用,
在调用时,block 通过FuncPtr 指针,找到对应的函数实现体,并将block本身以及参数传递进去。
为什么说,block是对象呢??
因为在block的编译运行的过程中,block会拥有ias指针(指代block 的类型),我们知道runtime中的objc_object&objc_class 也有isa 指针所以说其具有对象的性质,故而是对象。

首先,block会被编译器,编译成一个函数:
static void I文件_方法名称

impl_0 全称_类名_block_method_impl_0

block的声明变化--->impl_0 的结构体,有三个参数:_func_0 函数指针,第二参数:是block的相关描述的结构体,第三个是外部变量:(mutiplier 自定义的名称)

而在这个函数题中,包含有一个_block_impl 结构体
他的成员变量 中包含有isa,flags,FuncPtr,Desc的进行赋值。

将该结构体作为参数传递到_func_0 的结构中。第一个参数:_block_impl 第二个参数:num(调用的值)

(2)block截获变量的相关问题


屏幕快照 2020-01-07 上午5.39.27.png

局部变量:基本数据类型、对象类型

静态局部变量、全局变量、静态全局变量

简单回答:就是在使用局部变量的时候,会使用block的初始化的变量值。

分类回答:
对于基本数据类型截获其值。
对于对象类型局部变量,连同所有权修饰符一起截获。
局部静态变量:以指针的形式进行截获。
全局变量&&静态全局变量 不进行截获。

通过对编译后的源码的分析:_impl_0 结构体进行分析。

(3)__block的修饰符

添加情况:
一般情况下,对被截获变量进行赋值或者创建操作的时候,需要添加.

屏幕快照 2020-01-07 上午6.07.16.png

不需要添加修饰符的:静态局部变量(指针形,操作的是外部变量)、全局变量、静态全局变量

__block修饰后,就变成了对象。对象的结构体中包含有与自己同名 的成员变量,以及__forwarding 指针。
屏幕快照 2020-01-07 上午6.14.07.png

通过他的__forwarding指针找到像对应的成员变量,进行赋值的操作。

在栈上面创建的__block ,其 __forewarding 指向__block变量
屏幕快照 2020-01-07 上午6.19.46.png

本身

(4)block的内存管理

分类:全局block 栈block 堆block;

block的copy效果:

全局的Copy 相当于什么也没做;
栈block 被 copy到堆区中,
堆block 引用计数+1;

栈block的销毁过程:


屏幕快照 2020-01-07 上午6.28.31.png

栈的block copy过程(MRC 会出现内存泄漏问题)


屏幕快照 2020-01-07 上午6.31.47.png

栈上面__block 变量的copy过程:当栈上面的__block 变量,copy后,其后修改的都是对上面的变量。是通过__forwarding完成的。

屏幕快照 2020-01-07 上午6.33.56.png

(5)循环引用问题

ARC的block 引用方式:


屏幕快照 2020-01-07 上午6.44.42.png
屏幕快照 2020-01-07 上午6.45.42.png

这种解决方案:如果不调用,就会一直存在,循环引用。

block为什么会产生循环引用?
(1)如果说block对当前成员变量截获,他会对该变量进行一个强持有,而该成员变量也会对block 的本身有一个强持有,就产生了自循环的引用方式。__weak 移除。
(2)__block 修饰的变量(ARC出现问题,断环方式解决)

都会遇到哪些循环引用?(block,NSTimer)

__forwarding 具体使用方法??

你可能感兴趣的:(Block的相关问题)