iOS开发面试只需知道这些,技术基本通关!(block篇)

会挽雕弓如满月,西北望,射天狼。这篇文章主要讲述iOS开发面试只需知道这些,技术基本通关!(block篇)相关的知识,希望能为你提供帮助。

iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

一、什么是Block?Block 是将函数及其执行上下文封装起来的对象。
比如:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

通过 clang -rewrite-objc WYTest.m 命令编译该.m文件,发现该 block 被编译成这个形式:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

其中 WYTest 是文件名,blockTest 是方法名,这些可以忽略。其中WYTest blockTest_block_impl_0 结构体为
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

--block_impl 结构体为
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

block内部有isa指针,所以说其本质也是 OC 对象
block 内部则为:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

所以说 Block 是将函数及其执行上下文封装起来的对象
既然 block 内部封装了函数,那么它同样也有参数和返回值。
二、Block变量截获 1、局部变量截获 是值截获。 比如:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

这里的输出是 6 而不是 2,原因就是对局部变量 num的截获是值截获。同样,在block里如果修改变量 num,也是无效的,甚至编译器会报错。
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

打印为 1,2,3
局部对象变量也是一样,截获的是值,而不是指针,在外部将其置为 nil,对block 没有影响,而该对象调用方法会影响
2、局部静态变量截获 是指针截获。
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

输出为 2,意味着 num = 1 这里的修改num值是有效的,即是指针截获。同样,在 block里去修改变量 m,也是有效的。
##3、全局变量,静态全局变量截获:不截获,直接取值。
我们同样用clang 编译看下结果。
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

编译后
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

impl.isa= & _NSConcreteStackBlock; 这里注意到这一句,即说明该block是栈 block
可以看到局部变量被编译成值形式,而静态变量被编成指针形式,全局变量并未截获。而--block修饰的变量也是以指针形式截获的,并且生成了一个新的结构体对象:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

该对象有个属性:num5,即我们用--block 修饰的变量。这里--forwarding是指向自身的(栈 block)。
一般情况下,如果我们要对block 截获的局部变量进行赋值操作需添加--block 修饰符,而对全局变量,静态变量是不需要添加--block 修饰符的。
另外,block里访问 self 或成员变量都会去截获self
三、Block的几种形式分为全局 Block(_NSConcreteGlobalBlock)、栈 Block(_NSConcreteStackBlock)、堆
Block(_NSConcreteMallocBlock)三种形式
其中栈 Block 存储在栈(stack)区,堆 Block 存储在堆(heap)区,全局Block 存储在已初始化数据(.data)
##1、不使用外部变量的block是全局block
比如:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

输出:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

2、使用外部变量并且未进行copy操作的block是栈block比如:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

输出:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

日常开发常用于这种情况:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

##3、对栈block进行copy操作,就是堆block,而对全局block 进行copy,仍是全局block
比如堆 1中的全局进行copy 操作,即赋值:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

输出:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

仍是全局block
而对 2中的栈block 进行赋值操作:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

输出:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

对栈 blockcopy之后,并不代表着栈 block就消失了,左边的 mallock是堆 block,右边被copy的仍是栈block
比如:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

输出:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

即如果对栈Block进行cop,将会copy到堆区,对堆Block进行copy,将会增加引用计数,对全局
Block进行copy,因为是已经初始化的,所以什么也不做。
另外,--block变量在copy 时,由于--forwarding 的存在,栈上的--forwarding 指针会指向堆上的--forwarding变量,而堆上的--forwarding 指针指向其自身,所以,如果对--block 的修改,实际上是在修改堆上的--block变量。
--forwarding 指针存在的意义就是,无论在任何内存位置,都可以顺利地访问同一个 --block 变量。
另外由于block 捕获的 --block 修饰的变量会去持有变量,那么如果用 --block修饰 self,且 self 持有
block,并且 block内部使用到--block修饰的 self时,就会造成多循环引用,即 self持有 blockblock 持有--block 变量,而--block变量持有self,造成内存泄漏。
比如:
iOS开发面试只需知道这些,技术基本通关!(block篇)

文章图片

如果要解决这种循环引用,可以主动断开--block变量对self的持有,即在 block内部使用完weakself后, 将其置为 nil,但这种方式有个问题,如果 block 一直不被调用,那么循环引用将一直存在。
所以,我们最好还是用--weak来修饰 self
【iOS开发面试只需知道这些,技术基本通关!(block篇)】以上就是block篇的面试题合集了,感谢观看~!

    推荐阅读