大家好,我是面试聊iOS的程序员。
这篇文章将和大家分享面试iOS时聊Block一般都可以聊些什么。
抖音搜索 面试聊iOS 观看视频版
相关文章链接
面试聊iOS:内存管理
面试聊iOS:RunTime(一)
面试聊iOS:RunTime(二)
面试聊iOS:Block
面试聊iOS:多线程
面试聊iOS:RunLoop
面试聊iOS:性能优化
Block原理
block实际上就是OC对于闭包的实现
闭包是一个函数(或指向函数的指针),再加上该函数执行的外部的上下文变量
block本质上也是一个OC对象,因为它内部有isa指针
block封装了函数调用以及函数调用环境的OC对象
block是一个结构体,通常包含两个成员变量:__block_impl、__block_desc和一个构造函数。
__block_impl {
void * isa; // isa指针,指向一个类对象,有三种类型
int Flags; // 负载信息(引用计数和类型信息),按位存储
void *FuncPtr; // 指向block执行时的函数指针
}
1、通过block结构体的构造方法生成一个实例,并用一个指针指向当前实例
2、通过block->FuncPtr找到要执行的函数指针
Block类型
NSGlobalBlock 全局block
没有访问外部auto变量(我们平时写的局部变量,默认就有 auto,自动变量,离开作用域就销毁),访问外部static或者全局变量还是全局block
NSStackBlock 栈block
访问了外部auto变量(在ARC下没有强引用指向这个block,而是直接打印出来)
NSMallocBlock 堆block
栈block调用了copy(在ARC下访问了auto变量且有强引用指向该block或作为函数的返回值,就会自动将栈block copy到堆上)
全局block调用copy还是全局block,堆block调用copy引用计数+1
变量捕获
局部变量为什么要捕获?
考虑作用域的问题,在block里属于跨函数来访问局部变量,所以需要捕获
auto变量值传递,static变量指针传递
auto变量可能会销毁,内存可能会消失,不采用指针访问;static变量一直保存在内存中,采用指针访问
全局变量不需要捕获,直接访问
block里访问self会捕获self
OC函数转成C++函数时,self和_cmd作为函数默认传的参数,是局部变量,所以要捕获。
block里访问成员变量是先捕获self,然后通过self访问成员变量
__block、__weak
__block不管是MRC、还是ARC下都可以使用,可以修饰对象,也可以修饰基本数据类型;
__weak只能在ARC下使用,只能修饰对象,不能修饰基本数据类型;
__block对象可以在block中被重新赋值,__weak不可以
解决循环引用
在ARC下使用__weak,在MRC下使用__block
修改变量
__block修饰的变量在block中保存的是变量的地址,使用__block修饰之后的变量类似于static变量
__block不能修饰全局变量、静态变量(static)
weakSelf
如果block在栈空间,不管外部变量是强引用还是弱引用,block都会弱引用访问对象;
�如果block在堆空间,如果外部强引用,block内部也是强引用,如果外部弱引用,block内部也是弱引用
__weak typedof(self) weakSelf = self;
- block是controller的属性,如果内部没有使用weakSelf会造成内存泄漏
- block不是controller的属性,内部使用self不会造成内存泄漏
- 当使用类方法有block作为参数使用时,block内部使用self不会造成内存泄漏