ReactiveObjC

基础知识

常用的 RACSignal为冷信号 RACSubject为热信号
冷信号 即为订阅之后才开始执行的消息,订阅几次 就执行几次
热信号 为创建信号就开始执行的消息 无需订阅

常用类

RCASignal信号

//1.创建信号 

//可以在创建信号中立即发送信号 但是不能在block结束返回前销毁该信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"发送的消息内容"];
        return nil;
}];
//立即发送给定的错误信息
NSError *error = [[NSError alloc] init];
[RACSignal error:error];
//返回一个信号 该信号立即发送给定值 然后 complete
[RACSignal return:@"value"];
//返回信号 该信号直接 complete
[RACSignal empty];

//2.信号处理

//2.1 concat 返回一个信号signal3 当signal1 complete时订阅信号就signal2信号变化 我们可以通过订阅 signal3 来收到信号两个信号的值变化
RACSignal *signal3 = [signal1 concat:signal2]

//2.2  flattenMap 串联信号 当收到第一个消息的值变化时 开始执行第二个信号 此时我们订阅信号2  只会收到信号2值改变信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@"发送的消息内容"];
        });
        return nil;
    }];
RACSignal *signal2 = [signal flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
    return  [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"signal2 发送的消息内容"];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@"signal2 3秒后发送的消息内容"];
        });
        return nil;
    }];
}];

//2.2 map 对信号1中收到的值进行处理返回信号2 
RACSignal *signal2 = [signal map:^id _Nullable(NSString *  _Nullable value) {
    return [value substringFromIndex:2];
}];

//2.3 filter 过滤信号值
RACSignal *signal2 = [signal filter:^BOOL(NSString *  _Nullable value) {
    return YES;
}];

//2.4 ignore 忽略特定值的信号
RACSignal *signal2 = [signal ignore:@"发送的消"];

//2.5 startwith: 将这个值 拼接到信号值开头 返回新的信号 
RACSignal *signal2 = [signal startWith:@"start with发送的消息内容"];

//2.6 skip: 忽略开始的count个信号值改变
RACSignal *signal2 = [signal skip:1];

//2.7 take: 返回一个只接收前count个信号的信号值改变  其后发送的信号会失败
RACSignal *signal2 = [signal take:2];

//2.8  scanWithStart: reduce: 遍历信号1值变化 block中next即为信号1的信号值  
//      running为累计值 初始为start值 
RACSignal *signal2 = [signal scanWithStart:@"1" reduce:^NSString * _Nullable(NSString *  _Nullable running, NSString *  _Nullable next) {
    running = [[NSMutableString stringWithFormat:@"%@%@", running, next] copy];
    return running;
}];

//2.9 takeUntilBlock: 忽略这符合条件的信号以及之后的信号
//     takeWhileBlock: 返回符合条件的信号值
//      skipUntilBlock: 只返回符合条件以及之后的信号
//      skipWhileBlock: 忽略符合条件的信号
RACSignal *signal2 = [signal takeUntilBlock:^BOOL(NSString *  _Nullable x) {
    return [x hasPrefix:@"3秒"];
}];

//2.10 distinctUntilChanged 只返回值不一样的信号
RACSignal *signal2 = [signal distinctUntilChanged];


//3. 订阅

//subscribeNext: 订阅信号值改变  error 订阅错误信号 completed 订阅完成信号 
RACDisposable *disposable = [signal3 subscribeNext:^(NSString *  _Nullable x) {
    NSLog(@"signal3收到订阅值:%@", x);
} error:^(NSError * _Nullable error) {
    NSLog(@"signal3收到错误订阅:%@," error);
} completed:^{
    NSLog(@"signal3收到成功订阅;");
}];

//取消订阅
[disposable dispose];


RACSubject信号

//RACSubject 继承于 RACSignal 使用这个对象 可以直接发送和接收信号值改变  而不需要关心 创建信号和注销订阅问题
RACSubject *subject = [RACSubject subject];

[subject subscribeNext:^(NSString *x) {
    NSLog(@"接受新值%@", x);
} completed:^{
    NSLog(@"接受完成情况");
}];

[subject sendNext:@"新的值1"];

RACTuple 元组

元组功能

NSArray NSDictionary 集合操作

RAC扩展了NSArray 和 NSDictionary 拥有 rac_sequence(RACSequence类)属性

RACSequence

    //1. 获取一个 发送集合中值改变的信号
    arr.rac_sequence.signal
    //2. 用信号来遍历集合
    [arr.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@", x);
    }];
    //3. head
    NSLog(@"第一个元素%@", arr.rac_sequence.head);
    //4. tail
    NSLog(@"除了第一个元素外的所有元素集合%@", arr.rac_sequence.tail);
    
    //5. 从左侧开始遍历 start: 累计的初始值 accumulator: 累计值 value:当前值 count: 最终值
    NSNumber *count = [intArr.rac_sequence foldLeftWithStart:@(10) reduce:^NSNumber* (NSNumber *accumulator, NSNumber *value) {
        NSLog(@"%@--- %@", accumulator, value);

        return @(accumulator.integerValue + value.integerValue);
    }];
    NSLog(@"%@", count);
    
    //6. 同样可以从右边开始遍历
    
    //7. 遍历集合 判断是否存在符合条件 当遇到block返回YES 返回YES不再执行
    BOOL exist = [intArr.rac_sequence any:^BOOL(NSNumber *value) {
        return value.integerValue == 2;
    }];
    NSLog(@"%@", exist ? @"存在" : @"不存在"); //存在
    //8. 遍历集合 判断是否所有元素都满足条件
    BOOL pass = [intArr.rac_sequence all:^BOOL(id  _Nullable value) {
        return [value isKindOfClass:[NSNumber class]];
    }];
    NSLog(@"%@", pass ? @"通过" : @"不通过"); //存在
    //9. 遍历集合找到第一个符合条件的元素
    id obj = [intArr.rac_sequence objectPassingTest:^BOOL(id  _Nullable value) {
        if ([value isKindOfClass:[NSNumber class]]) {
            NSNumber *value1 = (NSNumber *)value;
            if (value1.integerValue % 3 == 0) {
                return YES;
            }
        }
        return NO;
    }];
    NSLog(@"第一个通过测试的是%@", obj); //9
    
    //10. 用户动态生成sequenceh headblock和tailblock只会执行一次
    //是惰性加载生成的
    //必须保证headblock和tailblock是线程安全的
    RACSequence *sequence = [RACSequence sequenceWithHeadBlock:^id _Nullable{
        return @(11);
    } tailBlock:^RACSequence * _Nonnull{
        return [RACSequence sequenceWithHeadBlock:^id _Nullable{
            return @(11);
        } tailBlock:^RACSequence * _Nonnull{
            return [RACSequence sequenceWithHeadBlock:^id _Nullable{
                return @(22);
            } tailBlock:^RACSequence * _Nonnull{
                return @[@(33)].rac_sequence;
            }];
        }];
    }];
    
    [sequence.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@", x);
    }];

UI操作

UIControl

 RACSignal *signal = [self.btn rac_signalForControlEvents:UIControlEventTouchUpInside];
[signal subscribeNext:^(UIButton *  _Nullable x) {
    NSLog(@"");
}];

UIButton

//当 按钮被点击时 执行 command中的block
self.btn.rac_command 

RACCommand

//初始化command 用一个信号
self.btn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
        return [RACSignal empty];
    }];
    
//executionSignals  属性为 command执行时的信号
[self.btn.rac_command.executionSignals subscribeNext:^(RACSignal<id> * _Nullable x) {
    NSLog(@"信号值执行了");
}];
    

UITextfield

//rac_textSignal 获取textfield内容改变信号
[self.textfield.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
    NSLog(@"输出内容%@", x);
}];

NSNotification

//通知事件 无需主动移除通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"" object:nil] subscribeNext:^(NSNotification * _Nullable x) {
    
}];

Delegate

[[self.view rac_signalForSelector:@selector(nameBtnDidClick:)] subscribeNext:^(RACTuple * _Nullable x) {
    
}];

KVO

//这样设置KVO 无需主动移除
//监听btn frame变化 
[[self.btn rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id  _Nullable x) {
        
}];

//使用宏定义快捷设置KVO (推荐)
[RACObserve(self.btn, frame) subscribeNext:^(id  _Nullable x) {
    
}];