RAC常见用法
rac_signalForSelector : 代替代理
rac_valuesAndChangesForKeyPath: KVO
rac_signalForControlEvents:监听事件
rac_addObserverForName 代替通知
rac_textSignal:监听文本框文字改变
rac_liftSelector:withSignalsFromArray:Signals:当传入的Signals(信号数组),每一个signal都至少sendNext过一次,就会去触发第一个selector参数的方法。
之前总结了项目中的MVVM框架,有朋友问我详细的viewModel中的业务逻辑实现,记得之前在里面说过viewModel里面很多数据结构的绑定是建立在熟练掌握RAC技术的基础上,然后现在就总结几个常用的,非常好用的rac方法
常见宏
RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某个属性绑定
RACObserve(self, name) :监听某个对象的某个属性,返回的是信号。
@weakify(Obj)和@strongify(Obj)
RACTuplePack :把数据包装成RACTuple(元组类)
RACTupleUnpack:把RACTuple(元组类)解包成对应的数据
RACChannelTo 用于双向绑定的一个终端
一.模型练习
如果我们需要在viewModel中进行数据请求,然后在VC里面写业务逻辑,我们可以使用下面这个方法。首先我们在viewModel里面创建一个全局属性RACCommand的对象处理事件,然后初始化,要注意不能返回空的RACSignal信号,这里可以之间在return的时候create RACSignal 的对象,也可以自定义方法,因为我们要在RACSignal里面进行数据请求,发送数据等操作,所以我一般都是分开写的
比如这样在自定义的方法里面进行数据请求,然后用RACSubscriber发射数据。
// 发送数据
[subscriber sendNext:@"执行命令产生的数据"];
// *** 发送完成 **
[subscriber sendCompleted]; //这个一定要写
2步就可以把baseModel发送到VC里面,然后在VC里面
使用subscribeNext获取数据
二 逻辑判断
如果我们大家要把一些基本的业务逻辑判断,数据处理放在viewModel里面(推荐这样做)
1.我们以登录为例子,比如说登录按钮在账号密码没有输入的时候不能点击的方法
我们在viewModel里面声明这些,然后一个方法处理
_loginEnableSignal = [RACSignal combineLatest:@[RACObserve(self, account), RACObserve(self, pwd)]reduce:^id(NSString *account, NSString *pwd){
return@(account.length && pwd.length);
}];
然后是数据请求,
// 登录按钮的命令
@property(nonatomic, strong, readonly) RACCommand *loginCommand;
然后就可以按照 一 中所说的进行数据请求,发送数据什么的初始化RACCommand return RACSignal信号
2.然后就是在VC或者view里面处理事件了
// 1.给视图模型的账号和密码绑定信号
RAC(self.loginVM, account) =self.accountField.rac_textSignal;
RAC(self.loginVM, pwd) =self.pwdField.rac_textSignal;
给viewModel里面的变量赋值绑定
// 1.处理文本框业务逻辑--- 设置按钮是否能点击
RAC(self.loginBtn, enabled) =self.loginVM.loginEnableSignal;
登录按钮的点击属性绑定
最后就是监听登录按钮的点击,处理登录事件
三.给大家说一些简单的rac很方便的宏
1.
我们在有输入传值的时候常会判断值是否为空,有值或者lengh大于多少的时候按钮才能点击,在rac我们可以这样展示
就这一句话,就把按钮_btn的是否可点击的这个属性enabled就绑定在了输入框_filed上面。如果有多个输入框,就可以在字面量数组中添加需要绑定的输入框,在id中获取各个输入框输入的值。如果我们要判断输入的字符的长度,就可以return的时候加一个str.lengh的判断
2.
// 给label的text属性绑定了文本框改变的信号
RAC(self.label, text) =self.textField.rac_textSignal;
这个是使用KVO监听view的属性,当view的坐标改变的时候,就会输出打印坐标center的值
四 经常性需要一些事件的完成反馈,有的需要传值。我们用block的回调也完美的解决了这个问题,那么用RAC如何实现,我们看一下
// 1.创建信号
_subject = [RACSubject subject];
首先可以创建一个信号,然后订阅信号
[_subject subscribeNext:^(id x) {
_lab.text=x;
NSLog(@"接收到绑定信号处理完的信号:%@", x);
}];
最后发送一下信号就可以了
_num++;
[_subject sendNext:[NSString stringWithFormat:@"%ld",(long)_num]];
这样,_lab的text就能跟着_num的值改变了。
实际项目中我们这样用
在viewModel中创建一个全局对象
然后在VC中订阅信号
最后在view中绑定的按钮点击结果,发送信号,反馈给VC
注:loginCommand是数据请求中初始化的对象。
rac中有个map方法叫做映射,即把收到的信号转换成其他的类型传出去
如图就是把获取到的value前面拼接了一个ws然后再当做信号发出去
五.
一个页面里有四个接口,每一个接口返回都有对应的UI改变,所以要四个接口全部请求返回成功后,再去做UI刷新
//第一部分数据
RACSignal *section01Signal01 = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"section01数据请求");
[subscriber sendNext:@"section01请求到的数据"];
return nil;
}];
//第二部分数据
RACSignal *section01Signal02 = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"section02数据请求");
[subscriber sendNext:@"section02请求到的数据"];
return nil;
}];
//第三部分数据
RACSignal *section01Signal03 = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"section03数据请求");
[subscriber sendNext:@"section03请求到的数据"];
return nil;
}];
这是三个网络请求
//可以在所有信号请求完成之后再执行方法,只需把三个结果传出去即可
[self rac_liftSelector:@selector(refreshUI:::) withSignals:section01Signal01,section01Signal02,section01Signal03, nil];
就这样三个网络请求完成以后,收到三个完成的信号以后就可以调用刷新UI的方法。
贴个别人的例子可以直观查看学习:-------