iOS之block小结

101 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

什么是Block Block是将函数及其执行上下文封装起来的对象。 什么是Block调用 Block调用即是函数的调用。 Block的几种形式(类型) Block有三种形式,包括:

  • 全局Block(_NSConcreteGlobalBlock):当我们声明一个block时,如果这个block没有捕获外部的变量,那么这个block就位于全局区(已经初始化数据(.data)区)。
  • 栈Block(_NSConcreteStackBlock):
    • 1.ARC环境下,当我们声明并且定义了一个block,系统默认使用__strong修饰符,如果该Block捕获了外部变量,实质上是从__NSStackBlock__转变到__NSMallocBlock__的过程,只不过是系统帮我们完成了copy操作,将栈区的block迁移到堆区,延长了Block的生命周期。对于栈block而言,变量作用域结束,空间被回收。
    • 2。ARC环境下,如果我们在声明一个block的时候,使用了__weak或者__unsafe_unretained的修饰符,那么系统就不会做copy的操作,也就不会将其迁移到堆区。
  • 堆Block(_NSConcreteMallocBlock):
    • 1.在MRC环境下,我们需要手动调用copy方法可以将block迁移到堆区
    • 2.而在ARC环境下,__strong修饰的(默认)block捕获了外部变量就会位于堆区,NSMallocBlock支持retainrelease,会对区引用计数+1或-1.
    • 只有局部变量和定义的属性才会拷贝到堆区。
  1. 存储在程序的数据区域,在block内部没有引用任何外部变量。
  2. 使用外部变量并且未进行copy操作的block是栈block。
  3. 对栈block进行copy操作,就是堆block,对堆block进行copy,将会增加引用计数。对全局block进行copy,仍是全局block。 在什么场景下使用__block修饰符呢?
  • 1.对截获变量进行赋值造作需要添加__block修饰符(赋值 != 使用)。
  • 2.对局部变量(基本数据类型和对象类型进行赋值需要__block修饰符。其内部其实是对该__block对象进行拷贝,所以通过__block可以修改被截获变量的值且不会和外部变量互相影响。
  • 3.对静态局部变量、全局变量、静态变量不需要__block修饰符。 block的截获变量特性? 基本数据类型的局部变量 Block 可以截获其值。 对于对象类型的局部变量联通所有权修饰符一起截获。 局部静态变量以指针的形式进行截获。 全局变量和静态全局变量,block是不截获的。 weak打破Block循环引用原理

block内部操作的weakSelf的指针地址,它和self是两个不同的指针地址,即没有直接持有self,所以可以weakSelf可以打破self的循环引用关系self - block - weakSelf。