下面两个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才会触发,并且是返回所有子信号量的内容。