1.ReactiveCocoa开发中常见用法有哪些?
第1种:代替代理
rac_signalForSelector:用于替代代理
// 1.代替代理,
RACSubject// RAC方法:
可以判断下某个方法有没有调用//
只要self调用Selector就会产生一个信号//
rac_signalForSelector:监听某个对象调用某个方法[[selfrac_signalForSelector:@selector(didReceiveMemoryWarning)]subscribeNext:^(id x) { NSLog(@"控制器调用了didReceiveMemoryWarning");
}];
// 判断下redView有没有调用btnClick,就表示点击了按钮[[_redViewrac_signalForSelector:@selector(btnClick:)]subscribeNext:^(id x) {
NSLog(@"点击了按钮");
}];
第2种:代替KVO
rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变
[_redView rac_observeKeyPath:@"name"options:NSKeyValueObservingOptionNewobserver:nilblock:^(idvalue,NSDictionary*change,BOOLcausedByDealloc,BOOLaffectedOnlyLastComponent)
{
// 只要监听的属性一改变调用
NSLog(@"%@",_redView.name);
}];
// KVO:第二种,只要对象的值改变,就会产生信号,订阅信号
[[_redView rac_valuesForKeyPath:@"name"observer:nil] subscribeNext:^(idx) {
}];
第3种:监听事件
rac_signalForControlEvents:用于监听某个事件
// 只要按钮产生这个事件,就会产生一个信号[[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(idx) {
NSLog(@"按钮被点击%@",x);
}];
_btn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(idinput) {
NSLog(@"按钮点击");
return[RACSignal empty];
}];
第4种:代替通知
rac_addObserverForName:用于监听某个通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(idx) {
NSLog(@"%@",x);
}];
第5种:监听文本框文字改变
rac_textSignal:只要文本框发出改变就会发出这个信号
[_textField.rac_textSignal subscribeNext:^(idx) {
// x:文本框的文字
NSLog(@"%@",x);
}];
第6种:处理当界面有多次请求时,需要都获取到数据时,才能展示界面
rac_liftSelector:withSignalsFromArray:Signals:当传入的Signals(信号数组),每一个signal都至少sendNext过一次,就会去触发第一个selector参数的方法
RACSignal *requestHot = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"请求最热商品");
[subscriber sendNext:@"获取最热商品"];
returnnil;
}];
RACSignal *requestNew = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@"请求最新商品");//
[subscriber sendNext:@"获取最新商品"];
returnnil;
}];
// Selector调用:当所有信号都发送数据的时候调用// 数组存放信号// Selector注意点:参数根据数组元素决定
// Selector方法参数类型,就是信号传递出来数据
[selfrac_liftSelector:@selector(updateUI:data2:) withSignalsFromArray:@[requestHot,requestNew]];
}
// 只要两个请求都请求完成的时候才会调用
- (void)updateUI:(NSString*)data1 data2:(NSString*)data2
{
NSLog(@"%@ %@",data1,data2);
}
2.ReactiveCocoa常见宏
第一种
RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某个属性绑定
// 给某个对象的某个属性绑定一个信号,只要产生信号,就会把信号的内容给对象的属性赋值// 给label的text属性绑定一个信号RAC(_label,text) =_texfField.rac_textSignal;
第二种
RACObserve(self, name):监听某个对象的某个属性,返回的是信号
// 观察某个对象某个属性
[RACObserve(self, name) subscribeNext:^(idx) {
NSLog(@"%@",x);
}];
第三种
@weakify(Obj)和@strongify(Obj),一般两个都是配套使用,解决循环引用问题
第四种
RACTuplePack:把数据包装成RACTuple(元组类)
// RACTuplePack:快速把一些数据包装成元组类
RACTuple *tuple = RACTuplePack(@"123",@1);
第五种
RACTupleUnpack:把RACTuple(元组类)解包成对应的数据
// 参数:需要解析生成出来变量名
RACTupleUnpack(NSString*str,NSNumber*num) = tuple;NSLog(@"%@ %@",str,num);
3.ReactiveCocoa常见操作方法
ReactiveCocoa操作原理
所有的信号(RACSignal)都可以进行操作处理,因为所有操作方法都定义在RACStream.h中,因此只要继承RACStream就有了操作处理方法
ReactiveCocoa操作思想
运用的是Hook(钩子)思想,Hook是一种用于改变API(应用程序编程接口:方法)执行结果的技术.
Hook用处:截获API调用的技术。
Hook原理:在每次调用一个API返回结果之前,先执行你自己的方法,改变结果的输出
ReactiveCocoa核心方法bind
ReactiveCocoa操作的核心方法是bind(绑定),而且RAC中核心开发方式,也是绑定,之前的开发方式是赋值,而用RAC开发,应该把重心放在绑定,也就是可以在创建一个对象的时候,就绑定好以后想要做的事情,而不是等赋值之后在去做事情
核心方法bind的使用
RACSignal *bindSignal = [_textField.rac_textSignal bind:^RACStreamBindBlock{
// block调用时刻:只要一个信号被绑定就会调用.表示信号绑定完成
NSLog(@"源信号被绑定");
return^RACStream *(idvalue,BOOL*stop)
{
// RACStreamBindBlock什么时候调用:每次源信号发出内容,就会调用这个block
// value:源信号发出的内容
NSLog(@"源信号发出的内容:%@",value);
// RACStreamBindBlock作用:在这个block处理源信号的内容
value = [NSStringstringWithFormat:@"xmg%@",value];
// block返回值:信号(把处理完的值包装成一个信号,返回出去)
// 创建一个信号,并且这个信号的传递的值是我们处理完的值,
valuereturn[RACReturnSignalreturn:value];
};
}];
// 订阅绑定信号,不在是源信号
[bindSignal subscribeNext:^(idx) {
NSLog(@"%@",x);
}];
// 执行流程 /*1.文字改变源信号2.绑定源信号,
[_textField.rac_textSignalbind] * 调用bind返回绑定好的信号,
didSubscribe3.订阅绑定信号 * 创建订阅者 * 调用绑定信号的
didSubscribe4.执行绑定信号
didSubscribe5.执行bind方法传入的block6.订阅源信号7.只要源信号一发出内容,就会调用
id signal = bindingBlock(x, &stop); * signal:把值处理完的信号 */
ReactiveCocoa操作方法之映射(flattenMap,Map)
flattenMap:信号中信号,signalOfSignals
[[_textField.rac_textSignal flattenMap:^RACStream*(idvalue) {
// value:源信号的内容
value = [NSString stringWithFormat:@"xmg%@",value];
// 返回值:信号,把处理完的值包装成信号返回出去
return [RACReturnSignal return:value];}] subscribeNext:^(idx) {
// 订阅[RACReturnSignal return:value发送值 // x:绑定信号的值
NSLog(@"%@",x);
}];
map: 用于普通信号,信号发出普通值
[[_textField.rac_textSignal map:^id(idvalue) {
// value:源信号的内容
// 返回值,就是处理源信号的内容,直接返回
return [NSString stringWithFormat:@"----xmg%@",value];
}] subscribeNext:^(idx) {
NSLog(@"%@",x);
}];
FlatternMap和Map的区别
1.FlatternMap中的Block返回信号。
2.Map中的Block返回对象。
3.开发中,如果信号发出的值不是信号,映射一般使用Map
4.开发中,如果信号发出的值是信号,映射一般使用FlatternMap。
ReactiveCocoa操作方法之组合
concat:按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号
// concat:连接信号,有顺序的拼接,一定要等第一个信号完成的时候,第二个信号才会被激活
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACSubject subject];
// 组合信号RACSignal *signals = [signalAconcat:signalB];
// 订阅组合信号[signalssubscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 发送数据
[signalAsendNext:@1];
[signalA sendCompleted];
[signalBsendNext:@2];
then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号
RACSubject*signalA = [RACSubjectsubject];
RACSubject*signalB = [RACSubjectsubject]; // 组合
RACSignal*signals = [signalA then:^RACSignal*{
return signalB;
}];
[signals subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[signalA sendNext:@1];
[signalA sendCompleted];
[signalB sendNext:@2];
then跟concat区别:监听不到第一个信号的值,共同点都是必须第一个信号完成,第二个信号才会激活
merge: 把多个信号合并为一个信号,任何一个信号有新值的时候就会调用
// merge:合并,任何一个信号只要发送值,就能订阅RACSubject*signalA = [RACSubjectsubject];RACSubject*signalB = [RACSubjectsubject];RACSignal*signals = [signalA merge:signalB]; [signals subscribeNext:^(id x) {NSLog(@"%@",x); }]; [signalA sendNext:@1]; [signalB sendNext:@2]; [signalB sendNext:@3];
zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件
RACSubject*signalA = [RACSubjectsubject];
RACSubject*signalB = [RACSubjectsubject];
RACSignal*signals = [signalA zipWith:signalB];
[signals subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// zipWith:当两个信号都发出内容的时候,才能被订阅到
[signalA sendNext:@1];
[signalB sendNext:@2];
[signalB sendNext:@3];
[signalA sendNext:@4];
combineLatest:将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号
// 第一个参数:就是存放需要合并信号[[RACSignal combineLatest:@[_textField1.rac_textSignal,_textField2.rac_textSignal] reduce:^id(
NSString*str1,
NSString*str2)
{
NSLog(@"%@ ---- %@",str1,str2);
// block:只要任意一个信号发出内容,就会调用//
block参数个数:由信号决定
// block参数类型:block的参数就是信号发出值
// 把两个信号中的值聚合成哪个值
return@(str1.length && str2.length);
}] subscribeNext:^(idx) {
_btn.enabled = [x boolValue];
NSLog(@"%@",x);
}];
reduce聚合:用于信号发出的内容是元组,把信号发出元组的值聚合成一个值
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@1];returnnil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@2];
returnnil;
}];// 聚合// 常见的用法,(先组合在聚合)。
combineLatest:(id)signals reduce:(id (^)())reduceBlock
// reduce中的block简介:
// reduceblcok中的参数,有多少信号组合,reduceblcok就有多少参数,每个参数就是之前信号发出的内容
// reduceblcok的返回值:聚合信号之后的内容。
RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id(NSNumber*num1 ,NSNumber*num2){
return[NSStringstringWithFormat:@"%@ %@",num1,num2];
}];
[reduceSignal subscribeNext:^(idx) {NSLog(@"%@",x);
}];
ReactiveCocoa操作方法之过滤
filter:过滤信号,使用它可以获取满足条件的信号
ignore:忽略完某些值的信号
distinctUntilChanged:当上一次的值和当前的值有明显的变化就会发出信号,否则会被忽略掉
take:从开始一共取N次的信号
takeLast:取最后N次的信号,前提条件,订阅者必须调用完成,因为只有完成,就知道总共有多少信号
takeUntil:(RACSignal *):获取信号直到执行完这个信号
skip:(NSUInteger):跳过几个信号,不接受
switchToLatest:用于signalOfSignals(信号的信号),有时候信号也会发出信号,会在signalOfSignals中,获取signalOfSignals发送的最新信号
ReactiveCocoa操作方法之秩序
doNext: 执行Next之前,会先执行这个Block
doCompleted: 执行sendCompleted之前,会先执行这个Block
ReactiveCocoa操作方法之线程
deliverOn: 内容传递切换到制定线程中,副作用在原来线程中,把在创建信号时block中的代码称之为副作用
subscribeOn: 内容传递和副作用都会切换到制定线程中
ReactiveCocoa操作方法之时间
timeout:超时,可以让一个信号在一定的时间后,自动报错
interval 定时:每隔一段时间发出信号
delay: 延迟发送next
ReactiveCocoa操作方法之重复
retry重试 :只要失败,就会重新执行创建信号中的block,直到成功
replay重放:当一个信号被多次订阅,反复播放内容
throttle节流:当某个信号发送比较频繁时,可以使用节流,在某一段时间不发送信号内容,过了一段时间获取信号的最新内容发出
4.学习MVVM架构思想
(1)程序为什么要架构?
便于程序员开发和维护代码
(2)常见的架构思想有哪些?
MVC ---- M:模型 V:视图 C:控制器)
MVVM ----M:模型 V:视图+控制器 VM:视图模型
MVCS ---- M:模型 V:视图 C:控制器 S:服务类
VIPER ---- V:视图 I:交互器 P:展示器 E:实体 R:路由
(3)MVVM思想
模型(M):保存视图数据
视图+控制器(V):展示内容 + 如何展示
视图模型(VM):处理展示的业务逻辑,包括按钮的点击,数据的请求和解析