1.监听成员变量变化,当成员变量值被改变时触发,其实就是KVO机制使用场景,
通常有三个步骤
<1>. 给对象的成员变量添加监听
<2>. 实现监听回调
<3>. 取消监听;
而通过 RAC也可以实现,RAC的回调是通过block实现的
egOne: 值变化时发送一个请求,每次值被修改时就会调用此block,并把修改后的参数传进来
[RACObserve(self, self.navigationTitle) subscribeNext:^(NSString *x) {
[self questWithData];
}];
egOne:当一个titile为标题时发送请求
[[RACObserve(self, self.navigationTitle)
filter:^(NSString* value) {
if ([value hasPrefix:@"标题"]) {
return YES;
} else { return NO;
}
}]
subscribeNext:^(NSString * x) {
[self requestWithData];
}];
egThree:关于textfield的处理
平常我们检测textfield的变化都是这样
[self.accountText addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
- (void)textFieldDidChange:(UITextField *)textField {
if (textField == self.textfield ) {
if (self.textfield.length >= 11 ) {
[self requestWithData];
} else {
return NO;
}
}
}
现在我们使用RAC监听textfield的值的变化
// filter:满足了某一条件才往下执行,通过条件才执行subscribeNext 这个block,才执行下一步
[[self.textField.rac_textSignal filter:^(NSString *value) {
if (value.length != 13) {
return NO;
} else { return YES; }
}]
subscribeNext:^(NSString *x) {
[self requestWithData];
}];
egFour:
// 监听多个变量变化,当变量满足条件时,使button为可点击状态
[[RACSignal
combineLatest:@[self.nameText.rac_textSignal,
self.passText.rac_textSignal,
RACObserve(self, isConnected)
]
reduce:^(NSString *name, NSString *pass, NSNumber *connect){
return @(name.length > 0 && pass.length > 0 && ![connect boolValue]);
}]
subscribeNext:^(NSNumber *res){
if ([res boolValue]) {
NSLog(@"XXXXX send request");
}
}];
RACSignal�:
// RACSignal对象捕捉当前和未来的值。信号可以被观察者链接,组合和反应。信号实际上不会执行,直到它被订阅。
// RACSignal是个信号量类,他的基类RACStream,信号量类继承自流类,RACSequence也继承自RACStream,是RAC框架的数组类,
// 发送事件流给它的subscriber。目前总共有三种类型的事件:next、error、completed。一个signal在因error终止或者完成前,可以发送任意数量的next事件,subscribeNext事件发生时,方法中对应的block也会执行
// 使用category来为很多基本UIKit控件添加signal
//eg:RACSequence与NSArray的转换
NSArray *arr = @[@(1),@(2),@(3),@(4),@(5)];
RACSequence *seque = [arr rac_sequence]; // arr -> RACSequence
NSArray *arr2 = [seque array]; // RACSequence -> arr
RACSignal与RACSequence都属于流类,都继承于RACStream,他们有个共同的流动性特性, RACSequence属于人流车流的流动,RACSignal属于信号流
下面贴一段关于信号流使用详解的代码
// getRandomSiganl获取随机数的信号量
// createSignal只有在有人订阅时才会执行
// subscriber信号量的订阅者
// 当有人订阅这个信号量时 [subscriber sendNext:@(arc4random())];
RACSignal *getRandomSiganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@(arc4random())];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
}];
}];
// 订阅操作:subscribeNext
[getRandomSiganl subscribeNext:^(id x) {
}];
[getRandomSiganl subscribeNext:^(id x) {
}];
冷信号与热信号
// 冷信号默认什么都不做
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"subscribe"];
[subscriber sendCompleted];
return nil;
}];
// 加了下面的代码变成了热信号,block里的代码就会被执行
// 我们只是创建了一个signal,但因为没有subscribe,所以什么都不会发生
[signal subscribeCompleted:^{
}];
// 创建信号的另一种方式
RACSignal *abc = [@"a,b,c" componentsSeparatedByString:@","].rac_sequence.signal;
[abc subscribeNext:^(id x) {
NSLog(@"abc:%@",x);
}];
// UIView Categories
// 常用的UIView也都相应的category,比如UIAlertView,就不需要再用Delegate了
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"" message:@"" delegate:nil cancelButtonTitle:@"cancel" otherButtonTitles:@"ensure", nil];
[[alertView rac_buttonClickedSignal] subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
[alertView show
];
// UITableView
// rac_prepareForReuseSignal,它的作用是当cell即将要被重用时,告诉cell上有多个button,cell在初始化时给每个button都addTarget:action:forControlEvents,但被重用时需要先移除这些target,只要添加如下代码便可解决这个问题
[[[self.button
rac_signalForControlEvents:UIControlEventTouchUpInside]
takeUntil:self.rac_prepareForReuseSignal]
subscribeNext:^(UIButton *x) {
NSLog(@"x:%@",x);
}];
// Map:用来改变流中的值并用结果创建一个新的流
// 可以使用map操作来把接收的数据转换成想要的类型,只要它是个对象。
RACSequence *seque = [@"A,B,C" componentsSeparatedByString:@","].rac_sequence;
RACSequence *map = [seque map:^id(id value) {
return [value stringByAppendingString:value];
}];
NSLog(@"map:%@",map); // reson is AA BB CC
// Filter:用一个block来判断test每一个值,判断通过就把这个值加入到结果的流中
RACSequence *num = [@"1,2,3" componentsSeparatedByString:@","].rac_sequence;
RACSequence *fiter = [num filter:^BOOL(NSString *value) {
return (value.intValue % 2) == 0;
}];
NSLog(@"filter:%@",fiter); // reson is 2
// Concat:方法将一个流中的值加到另一个中
RACSequence *sequen = [@"A,B,C" componentsSeparatedByString:@","].rac_sequence;
RACSequence *number = [@"1,2,3" componentsSeparatedByString:@","].rac_sequence;
RACSequence *connect = [sequen concat:number];
NSLog(@"connect:%@",connect);// reson is A B C 123
// 补充,非原创
// 补充,非原创: ReactiveCocoa
// RACSignal: 信号类,表示当数据改变时,信号内部会发出数据,本身不具备发送信号的能力,而是交给一个内部的订阅者去发出
// 默认一个信号都是冷信号,也就是值改变了也不会触发,只有订阅了这个信号才会变成热信号,然后值改变了才会触发
// 订阅信号: subscribeNext
// 1.RACSubscriber : 订阅者的意思,用于发送信号,这是一个协议,不是一个类,只要遵守这个协议,并且实现方法才能成为订阅者。通过create创建的信号,都有一个订阅者,帮助它发送数据
// 2.RACDisposable : 用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它; 不想监听某个信号时,可以通过它主动取消订阅信号
// 3.RACSubject : 信号提供者,自己可以充当信号,又能发送信号; 通常用来代替代理,有了它,就不用自定义代理
// 4.RACReplaySubject : 重复提供信号类,RACSubject的子类
// ***RACReplaySubject与RACSubject区别: RACReplaySubject可以先发送信号,在订阅信号,RACSubject就不可以。
// 使用场景一:如果一个信号每被订阅一次,就需要把之前的值重复发送一遍,使用重复提供信号类。
// 使用场景二:可以设置capacity数量来限制缓存的value的数量,即只缓充最新的几个值。
// RACSequence和RACTuple简单使用
// 字典转模型
// NSArray *numArr = @[@1,@2,@3,@4];
// // 把数组转化成RACSequence numArr.rac_sequence
// [numArr.rac_sequence.signal subscribeNext:^(id x) {
// NSLog(@"numArr.rac_sequence.signal:%@",x);
// }];
// // 遍历字典,遍历出来的键值对会包装成RACTuple(元祖对象)
// NSDictionary *dic = @{@"name":@"LiHua",@"age":@18};
// [dic.rac_sequence.signal subscribeNext:^(id x) {
// // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
// RACTupleUnpack(NSString *key,NSString *value) = x;
// // 相当于: // NSString *key = x[0]; NSString *value = x[1];
// NSLog(@"key:%@,value:%@",key,value);
// }];
RACCommand
调用执行成功返回信号的信号,主线程执行
@property (nonatomic, strong, readonly) RACSignal *executionSignals;
调用执行当前信号是否正在执行返回@(NO),主线程执行
@property (nonatomic, strong, readonly) RACSignal *executing;
默认情况下返回@NO信号,但只有一下两种情况会返回@YES
1.上面第二种创建RACCommand的时候就给isEnableSignal赋值为@YES的时候
2.allowsConcurrentExecution属性设置为 NO并且这个信号正在执行中. 主线程执行
@property (nonatomic, strong, readonly) RACSignal *enabled;
是否允许多个RACCommand同时执行。
@property (atomic, assign) BOOL allowsConcurrentExecution;
执行RACCommand的时候发送获取的error信号
@property (nonatomic, strong, readonly) RACSignal *errors;
调用RACCommand,input为executionSignals的订阅者发送的值
- (RACSignal *)execute:(id)input;