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) {
}];