iOS中 block 问题归纳

206 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情


前言

在iOS面试中,block这个问题出现的频率虽然不是最高的,但是会和很多实际开发过程中的问题结合起来问,所以弄懂其中原理还是比较重要的,下面咱们就来看看,block的一些关键原理把。

第一重:解释block

  • block是将函数及其执行上下文封装起来的对象

第二重:block截获变量

  • 局部变量
    • 基本数据类型(只截获其值)
    • 对象类型(连同所有权修饰符一起截获)
  • 静态局部变量(指针形式截获)
  • 全局变量(不截获)
  • 静态全局变量(不截获)

截屏2022-03-23 下午5.54.24.png

截屏2022-03-23 下午5.55.22.png

第三重:__block修饰符

  • 对被截获变量进行赋值操作就需要添加__block
  • 赋值 不等于 使用
  1. 需要__block修饰符的 【局部变量(基本数据类型、对象类型)】

  2. 不需要__block修饰的

    1) 静态局部变量

    2)全局变量

    3)静态全局变量

第四重:block内存管理

  • _NSConcreteGlobalBlock(全局)
  • _NSConcreteStackBlock(栈)
  • _NSConcreteMallocBlock(堆)

截屏2022-03-23 下午5.59.44.png

Block的copy操作

截屏2022-03-23 下午6.00.22.png

第五重:block循环引用

为什么会产生循环引用?

1,如果当前block对当前对象的某一成员变量进行截获的话,就会对这个成员变量进行强引用,同时当前对象也对这个block进行copy修饰,也是一个强引用,所以会产生自循环引用,可以通过声明其为__weak变量,从而进行消除

2,如果说我们声明一个__block修饰符的话,在MRC下不会产生(因为不会产生引用计数),在ARC下我们可以通过断环的方式进行打破循环引用

Ps:为了保证block的释放正和时宜,而不是像在栈空间上的变量似的随时可能被释放。在MRC的时候声明一个block的时候通常使用copy关键字修饰,而到了ARC虽然不用我们显式的执行copy,为了提醒我们block是通过copy操作存在于堆空间的我们还是会用copy关键修饰,这只是一个习惯,其实用strong也是可以的。