RAC系列1之 链式/函数式/响应式编程
链式编程
提到链式编程我们最常见的就是Masonry框架了,那么我们先来分析一下该框架:
- Masonry的分析:
- 使用Masonry约束布局步骤
- 使用Masonry约束布局步骤
- 若使用Masonry,就不能在使用xib/sb,因为该框架内部自动添加有约束
- 使用Masonry约束布局步骤
- mas_makeConstraints执行流程:
- 取消控件自动约束,创建约束制造者MASConstraintMaker,绑定控件,生成了一个保存所有约束的数组
- 执行mas_makeConstraints传入进行的block
- 让约束制造者安装约束
- 清空之前的所有约束(底层用到runtime获得对象的所有约束属性)
- 遍历约束数组,一个一个安装
- 清空约束数组
-
代码举例:
// 创建红色view UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; // 设置约束,一定要先把view添加上去,才能设置约束 [redView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.top.equalTo(@10); make.right.bottom.equalTo(@-10); }];
- 我们点击进入查看
make.left.top.equalTo(@10);
该段代码,可以得出如下结论:- 链式编程思想格式:将各个方法用点语法连接起来.
make.left.top.equalTo(@10);
- 优点: 将多个操作用”.”连接一起,可读性好
- 特点:(这里的block也可以是函数)
- 方法的返回值必须为方法的调用者或者block
- 若返回为block:把需要操作的值当做block参数,block也需要返回值,就是方法调用者
- 方法一定没有输入参数
- 方法的实现与block的实现全部在内部,外部只是调用
- 链式编程思想格式:将各个方法用点语法连接起来.
-
举例使用
//1. 链式编程的实现 #import <Foundation/Foundation.h> @interface CalculateManager : NSObject //保存计算的结果 @property (nonatomic,assign) NSInteger result; //方法返回block -(CalculateManager *(^)(NSInteger))add; @end #import "CalculateManager.h" @implementation CalculateManager -(CalculateManager* (^)(NSInteger))add{ //block的实现,block返回方法调用者 return ^(NSInteger value){ _result += value; return self; }; } @end //ViewController方法中调用 - (void)test { CalculateManager *mag = [[CalculateManager alloc] init]; mag.add(5).add(6).add(7); NSLog(@"====%zd",mag.result); } 2.模仿masonry //给NSObject分类添加一个加法计算方法 #import <Foundation/Foundation.h> #import "CalculateManager.h" @interface NSObject (Caculate) //方法的参数为block +(NSInteger)zh_makeCaculate:(void(^)(CalculateManager *manager))block; @end #import "NSObject+Caculate.h" @implementation NSObject (Caculate) +(NSInteger)zh_makeCaculate:(void (^)(CalculateManager *))block{ //创建block参数 CalculateManager *magr = [[CalculateManager alloc] init]; //调用block block(magr); return magr.result; } @end //调用 //模仿masonry - (void)test2 { //调用NSObject的分类方法,传入block参数 NSInteger result = [NSObject zh_makeCaculate:^(CalculateManager *manager) { //block的内部实现:调用manager的block // 用block替代方法 // 把怎么计算的代码封装到block manager.add(5).add(6).add(7); }]; NSLog(@"%zd",result); }
函数式编程
- 函数式编程总结:(block也可以是函数)
-
样式:一个方法连接一个block实现(一直连续)
[...[[p 方法:^{ //代码 }] 方法:^{ //代码 }]...];
- 函数式编程本质:就是往方法中传入block,方法中嵌套block调用,把代码集合起来管理.
- 特点:
- 方法返回值一定是对象本身,方法传入参数一定是block
- block返回值为计算结果,block参数为操作数
- 计算过程在外部,内部调用并接收block的返回值
-
-
举例:
//用函数式编程实现,写一个加法计算器,并且加法计算器自带判断是否等于某个值 #import <Foundation/Foundation.h> @interface CalculateManager : NSObject @property (nonatomic, assign) int result; @property (nonatomic,assign) BOOL isEqual; // 计算 - (instancetype)calculate:(int(^)(int))calculateBlock; // 计算 - (instancetype)equal:(BOOL(^)(int result))operation; @end #import "CalculateManager.h" @implementation CalculateManager - (instancetype)calculate:(int (^)(int))calculateBlock { _result = calculateBlock(_result); return self; } -(instancetype)equal:(BOOL (^)(int result))operation{ _isEqual = operation(_result); return self; } @end //调用 #import "ViewController.h" #import "CalculateManager.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //获得计算结果 CalculateManager *mgr = [[CalculateManager alloc] init]; int result = [[mgr calculate:^(int result){ // 存放所有的计算代码 result += 5; result *= 5; return result; }] result]; NSLog(@"%d",result); //计算结果,然后判断是否等于10 BOOL isEqual = [[[mgr calculate:^int(int result) { result += 2; result *= 5; return result; }] equal:^BOOL(int result) { return result == 10; }] isEqual ]; NSLog(@"相等吗??%zd",isEqual); } @end
- 链式编程与函数式编程比较:
- 样式:
- 链式编程是将多行代码通过”.”连接在一起,可读性好
- 函数式编程是往方法中传入block,方法中嵌套block调用,把代码集合起来管理.
- 特点:
- 链式返回值是方法调用者或者block,实现在内部,调用在外部,方法无参数
- 函数式返回值一定是方法调用者,参数为block,实现在外部,调用在内部
- 样式:
响应式编程
什么是响应式编程?这是一个很抽象的概念,我晕了好久才理解.
知乎上有一位是这样说的:
- 响应式编程:顾名思义,就是针对不同的响应来进行编程.
- 事件A就几种结果(响应),我们根据不同的结果(响应)进行不同的处理
- 响应式编程的必备条件:
- 监听事件A有几种结果(响应)
- 根据监听,一旦事件A做出某种结果(响应),我们针对不同响应做出不同的事情
- 响应式编程的特点:不管你A到底做了什么事,我仅仅关注你A的结果,根据A的不同结果我做不同的事
- 响应式编程到处都在,只是我们不能抽象理解:
- 同步线程中
int a = 0; //事件A { //这里处理代码(可能会修改a的值),至于干什么我们不管,只监听a的值 } //这里的if语句就相当于是监听A事件的结果了 if(a == 0){ //处理1 }else if (a == 1){ //处理2 }....
-
异步线程
int a = 0; //事件A: { //异步网络请求.... //网请求回来时 { //可能处理a,也可能不处理,我们不管 //监听: 拿到a的结果,向外界发出通知(通知观察者) } } //其他代码... //观察者: { //没有通知我(调用我的方法),等待... //一旦有结果(得到响应) //根据不同响应做不同处理 }
- 同步线程中
- 响应式它是依赖于事件的,响应式的代码它的运行不是按代码的顺序,而是跟多个按时间发生的事件有关.这些按时间排列的事件,被称为”流”,stream
- 响应式编程本身是建立于观察者模式之上的一种编程范式.说白了我感觉响应式编程,就是实现观察者模式,时刻监听事件,然后根据监听时刻做出响应.
- 在响应式编程中,”监听”流的行为叫做订阅; 执行响应的就是观察者;这个流就是被观察的主体(subject).
- 举例:KVO就是响应式编程的体现(不在举例)