iOS block 的两大常见用法

1.block是什么❓

block在其他语言里又称闭包,可以叫匿名函数,代码块

2.block有什么作用❓

block的声明和实现一般不在一个类里,在一个类里也就没什么意思了,他的主要作用就是保存一个代码块,在声明的类里获取当前类的一些变量,然后传递到另一个block实现的类里面去执行,这也就完成了他的使命,对象间的传值和通信

3.block的常见两大用途

反向传值,正向就没必要了,属性 单例都很好实现,而且你把block的调用和实现都写在一个类里,绝对有人说你煞笔

封装一些网络请求类,通过block作为方法的参数,比如UIview带block的那个动画

4.block的声明

typedef void (^RequestBlock)(NSString *name); 无返回值带参数的block

另外block作为属性的时候一定要用copy,因为比如一个方法或者函数,都是在栈区,当期函数执行完就不存在了,而block是声明在栈区,但是他并不是立即执行的,需要等到block调用的时候才去执行block实现的那部分代码块,所以需要拷贝一份到堆区,像对象一样,大家都知道对象的内存都在堆区,通过在栈区的指针变量引用,也就是你的 *变量 保存的实际上是堆区的内存地址

5.block 的一些常见问题

block内部不能修改变量值,这个是有原因的,因为block相当于一个快照,他获取外部的变量是苹果的runtime机制实现的,以参数列表的形式传递进去的,所以不能修改值,解决办法是加上__block来修饰外部变量,为什么加上__block就可以了呢? 其实也没什么神奇的,加上__block之后传递的不再是变量的值了,而是变量的指针就是地址,像对象一样,传入blcok的是对象地址,所以通过地址获取的变量可以在block内部被修改, 简单的说, 局部变量被 block 捕获的只是他的值得一个 copy,  static 全局变量, 或者__ block 来修饰的变量捕获的是变量的地址, 关于详细的请看我的另一篇博客<<深入了解 ios block的内部结构>>, 其实 block 就是一个结构体.

还有就是block内部的循环引用问题,block会被内部被引用的对象做一次强引用,所以一般在外部引用过block,在内部又要被引用的,最好在block外部先用__weak 来修饰,其原理就是__weak 修饰的变量,当对象销毁的时候,指针变量会自动置为Nil,这样就不会一直循环引用,导致不能释放,如果在内部对象需要强用,可以再用__strong 修饰,网上有个@weakIfy 和@strongIfy ,其原理也是通过c语言实现weak和strong绑定到变量上

6.block的定义和声明究竟应该在哪里?

这是很多人迷茫的地方

像代理一样,你需要从第二个页面传值到第一个页面,就需要在第二个页面定义代理方法,让第一个页面做他的代理,去实现代理方法,也就是说哪个页面有值需要传递,哪个页面里定义协议方法,谁实现他的方法,谁就是他的代理,参数就传递给谁

blcok也是如此,在你需要传值的类里定义声明block,然后在一个合适的时候调用blcok,self.blcok("需要传递的参数"),或者-(void)functionWithBlock:blo{bl0("需要传递的参数")} 在方法的实现里调用block.然后在你需要传往的页面里实现block, [instance functionWithBlock:^("传递过来的参数"){ 利用你传递过来的参数执行你需要的操作}],你可能会问这个时候block还存在吗? 因为block是当前类的属性,且用了copy,所以在当前对象的生命周期内他都是存在的.

下面贴几张图供大家更好地理解

这是一个假设的封装的网络请求类,有一个方法带有block参数,发起网络请求,然后在block里执行请求成功之后需要执行的操作

网络请求类的 .m 文件 发起请求 blcok()调用

这是第一个控制器 执行网络请求 接收第二个控制器传递过来的值(反向传值)

这是第二个控制器 向第一个控制器传值

原文地址:https://www.cnblogs.com/ChrisZhou666/p/6494761.html