下面两个demo的demo地址。
iOS RAC下对应的的Target Action模式、代理模式和观察者模式
Demo1:当输入的用户名不为空且密码长度大于6时,登录按钮可点,否则不可点
分析:将两个输入框转化成信号量,并进行绑定,然后使用map进行映射返回新的信号量,用RAC()绑定在button的enable属性上,
- (void)viewDidLoad {
[super viewDidLoad];
/*
将TextField的输入转化为信号量
*/
RACSignal *userNameSignal = self.userNameTF.rac_textSignal;
RACSignal *psdSignal = self.psdTF.rac_textSignal;
/*
合并两个输入框的信号量,并使用map对信号量返回值进行映射使其返回bool值,
*/
RACSignal *bigSignal = [[RACSignal combineLatest:@[userNameSignal,psdSignal]] map:^id _Nullable(RACTuple * _Nullable value) {
RACTupleUnpack(NSString *username , NSString *psd) = value;
//@()将值变量装箱成对象
return @([username length]>0 && [psd length]>6);
}];
/*
使用RAC将一个信号量绑定在一个属性上
*/
RAC(self.loginBtn, enabled) = bigSignal;
}
使用到的RAC知识点:
rac_textSignal--监听文本框文字改变,对应UITextField 、UItextView
combineLatest--将多个信号量合并,返回一个新的信号量,当每一个子信号量都有过一次sendNext时,子信号触发才会才会触发合并信号并返回每一个子信号的最新值。
map--把一个信号量的内容映射成新的内容。
RACTupleUnpack--将RACTuple(元祖类)解包成对应的数据
RAC(Target,Keypath)--将一个对象的某个属性绑定到一个信号量对应的内容上
Demo2:三个UISlider和三个UITextField分别对应R G B颜色值,当滑动滑块或者输入框输入时,改变当前view的背景颜色,且滑块和输入框之间可以互相改变对方的值。
分析:首先将每一对滑块和输入框都转成管道信号,然后对管道进行双向绑定,输出新的信号,共得到三个新的信号量分别对应RGB的颜色值,将R G B三个新的信号进行合并返回的信号用RAC()绑定到view的backgroundcolor的属性上。
- (void)viewDidLoad {
[super viewDidLoad];
RACSignal *redSignal = [self bindSlider:_redSlider withTF:_redTF];
RACSignal *greenSignal = [self bindSlider:_greenSlider withTF:_greenTF];
RACSignal *blueSignal = [self bindSlider:_blueSlider withTF:_blueTF];
RAC(self.showView,backgroundColor) = [[RACSignal combineLatest:@[redSignal , greenSignal , blueSignal]] map:^id _Nullable(RACTuple * _Nullable value) {
return [UIColor colorWithRed:[value[0] floatValue] green:[value[1] floatValue] blue:[value[2] floatValue] alpha:1];
}];
}
/*
绑定slider和输入框
*/
- (RACSignal *)bindSlider:(UISlider *)slider withTF:(UITextField *)TF
{
RACChannelTerminal *sliderChannel = [slider rac_newValueChannelWithNilValue:nil];
RACChannelTerminal *tfChannel = TF.rac_newTextChannel;
//执行一次,因为combineLatest需要合并的信号中每个至少sdnNext一次才会触发订阅
RACSignal *oneSignal = [TF.rac_textSignal take:1];
[tfChannel subscribe:sliderChannel];
[[sliderChannel map:^id _Nullable(id _Nullable value) {
return [NSString stringWithFormat:@"%.2f" , [value floatValue]];
}] subscribe:tfChannel];
//merge将多个信号合并成一个,订阅的话只有一个返回值
return [[sliderChannel merge:tfChannel]merge:oneSignal];;
}
第二个demo使用到的RAC知识点:
RACChannelTerminal--RACSignal的子类,通道终端,可以将两个RACChannelTerminal进行双向绑定
rac_newValueChannelWithNilValue--获取UISlider的通道终端,是RAC给UISlider添加的一个分类
rac_newTextChannel--获取UITextField的通道终端,也是一个分类
take:(NSinteget)count--使信号量触发多少次
subscribe--对两个通道终端进行绑定
merge--把多个信号量合并为一个新信号量,当任何一个子信号量触发时,都会触发这个新信号量,但是返回值只有被触发的子信号量的返回值。
PS:注意merge和combineLatest的区别,两个都是将多个信号量合并,但是merge是只要有子信号量触发就会返回该子信号量的内容,而combineLatest是当子信号量触发时,只有当其他信号量都触发过sendNext才会触发,并且是返回所有子信号量的内容。