函数式编程


函数式编程思想: 把操作尽量写成一系例嵌套的函数或者方法调用。

函数式编程本质: 就是往方法中传入Block,方法中嵌套Block调用,把代码聚合起来管理

函数式编程特点: 每个方法必须有返回值(本身对象),把函数或者Block当做参数,block参数(需要操作的值)block返回值(操作结果)

代表:ReactiveCocoa。

链式编程思想:是将多个操作(多行代码)通过点号(.)链接在一起成为一句代码,使代码可读性好。a(1).b(2).c(3)

链式编程特点:方法的返回值是block,block必须有返回值(本身对象),block参数(需要操作的值)

代表:Masonry框架。

##ReactiveCocoa常见类

学习框架首要之处:个人认为先要搞清楚框架中常用的类,在RAC中最核心的类RACSiganl,搞定这个类就能用ReactiveCocoa开发了。

  1. RACSiganl:信号类,一般表示将来有数据传递,只要有数据改变,信号内部接收到数据,就会马上发出数据。

注意:

  1. 信号类(RACSiganl),只是表示当数据改变时,信号内部会发出数据,它本身不具备发送信号的能力,而是交给内部一个订阅者去发出。
  1. 默认一个信号都是冷信号,也就是值改变了,也不会触发,只有订阅了这个信号,这个信号才会变为热信号,值改变了才会触发。
  1. 如何订阅信号:调用信号RACSignalsubscribeNext就能订阅
  1. RACSubscriber:表示订阅者的意思,用于发送信号,这是一个协议,不是一个类,只要遵守这个协议,并且实现方法才能成为订阅者。通过create创建的信号,都有一个订阅者,帮助他发送数据。
    `objc
    -(void)createSimpleSignal{
    // RACSignal使用步骤:
    // 1.创建信号 + (RACSignal )createSignal:(RACDisposable (^)(id subscriber))didSubscribe
    // 2.订阅信号,才会激活信号. - (RACDisposable * )subscribeNext:(void (^)(id x))nextBlock
    // 3.发送信号 - (void)sendNext:(id)value

// RACSignal底层实现:
// 1.创建信号,首先把didSubscribe保存到信号中,还不会触发。
// 2.当信号被订阅,也就是调用signal的subscribeNext:nextBlock
// 2.2 subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
// 2.1 subscribeNext内部会调用siganl的didSubscribe
// 3.siganl的didSubscribe中调用[subscriber sendNext:@1];
// 3.1 sendNext底层其实就是执行subscriber的nextBlock

// 1.创建信息
RACSignal signal = [RACSignal createSignal:^RACDisposable _Nullable(id subscriber) {
// block调用时刻:每当有订阅者订阅信号,就会调用block。
// 2.发送信号
[subscriber sendNext:@1];
// 如果不在发送数据,最好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。

[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
  // block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。

  // 执行完Block后,当前信号就不在被订阅了。
  NSLog(@"信号销毁了");

}];

}];
// 3. 订阅信号,才会激活信号
[signal subscribeNext:^(id x) {
// block调用时刻:每当有信号发出数据,就会调用block.
NSLog(@”接收到数据:%@”,x);
}];
}

3. `RACDisposable`:用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它。
**使用场景**: 不想监听某个信号时,可以通过它主动取消订阅信号。

4. `RACSubject`: 信号提供者,自己可以充当信号,又能发送信号。
**使用场景**: 通常用来代替代理,有了它,就不必要使用代理了
1. `RACReplaySubject`:重复提供信号类,`RACSubject`的子类。
> `RACReplaySubject`可以先发送信号,在订阅信号,`RACSubject`就不可以
**使用场景一**:如果一个信号每被订阅一次,就需要把之前的值重复发送一遍,使用重复提供信号类。
**使用场景二**:可以设置capacity数量来限制缓存的value的数量,即只缓充最新的几个值。

```objc
-(void)createRACSubject{


  // RACSubject使用步骤
  // 1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
  // 2.订阅信号 - (RACDisposable * ) subscribeNext:(void (^)(id x))nextBlock
  // 3.发送信号 sendNext:(id)value

  // RACSubject:底层实现和RACSignal不一样。
  // 1.调用subscribeNext订阅信号,只是把订阅者保存起来,并且订阅者的nextBlock已经赋值了。
  // 2.调用sendNext发送信号,遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock

  //1. 创建信号
  RACSubject * subject = [RACSubject subject];

  //2.订阅信号
  [subject subscribeNext:^(id   x) {
    // block调用时刻:当信号发出新值,就会调用.
    NSLog(@"第一个订阅都:%@",x);
  }];
  [subject subscribeNext:^(id   x) {
    // block调用时刻:当信号发出新值,就会调用.
    NSLog(@"第二个订阅都:%@",x);
  }];
  //3. 发送信息
  [subject sendNext:@"1"];

}
-(void)createReplaySubject{


  // RACReplaySubject使用步骤:
  // 1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
  // 2.可以先订阅信号,也可以先发送信号。
  // 2.1 订阅信号 - (RACDisposable * )subscribeNext:(void (^)(id x))nextBlock
  // 2.2 发送信号 sendNext:(id)value

  // RACReplaySubject:底层实现和RACSubject不一样。
  // 1.调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
  // 2.调用subscribeNext订阅信号,遍历保存的所有值,一个一个调用订阅者的nextBlock

  // 如果想当一个信号被订阅,就重复播放之前所有值,需要先发送信号,在订阅信号。
  // 也就是先保存值,在订阅值。

  //    1.创建信号
  RACReplaySubject * replaySuject = [RACReplaySubject subject];

  //    2. 发送信号
  [replaySuject sendNext:@1];
  [replaySuject sendNext:@2];

  //    3.订阅信号
  [replaySuject subscribeNext:^(id   x) {
    NSLog(@"第一个订阅者接收到的数据%@",x);

  }];
  [replaySuject subscribeNext:^(id   x) {
    NSLog(@" 第二个订阅者接收到的数据%@",x);

  }];

}

  1. RACTuple:元组类,类似NSArray,用来包装值.

  2. RACSequence:RAC中的集合类,用于代替NSArray,NSDictionary,可以使用它来快速遍历数组和字典。
    `objc
    -( void )RACIterator{
    // 1.遍历数组
    NSArray * numbers = @[@1,@3,@4];
    // 这里其实是三步
    // 第一步: 把数组转换成集合RACSequence numbers.rac_sequence
    // 第二步: 把集合RACSequence转换RACSignal信号类,numbers.rac_sequence.signal
    // 第三步: 订阅信号,激活信号,会自动把集合中的所有值,遍历出来。
    [numbers.rac_sequence.signal subscribeNext:^(id x) {

     NSLog(@"%@",x);
    

    }];

    // 2.遍历字典,遍历出来的键值对会包装成RACTuple(元组对象)
    NSDictionary dict = @{@”name”:@”yuanph”,@”age”:@18,@”country”:@”china”};
    [dict.rac_sequence.signal subscribeNext:^(RACTuple
    x) {

     // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
     RACTupleUnpack(NSString * key,NSString * value)= x;
     NSLog(@"%@:%@",key,value);
    

    }];
    }

`

  1. RACCommand:RAC中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程
    使用场景:监听按钮点击,网络请求

   转载规则


《函数式编程》 志鹏 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
pod command pod command
pod 基础使用命令 创建Podfile文件 pod init 使用命令打开Podfile文件open -a Xcode Podfile 搜索pod 库pod search 库名 更新本地Repo库pod repo update
2017-03-07
下一篇 
UITest 学习笔记 UITest 学习笔记
UITest是什么?UITest 是一个自动测试UI与交互的Testing组件 UITest有什么作用?它可以通过代编写代码/记录开发者的操作过程并代码化,来实现自动点击某个按钮/视图/自动输入文字等功能 UI Test 的重要性 在实际开
2017-02-27 志鹏
  目录