ReactiveCocoa 学习笔记 - 使用篇

1.ReactiveCocoa开发中常见用法有哪些?

第1种:代替代理

rac_signalForSelector:用于替代代理

[objc]view plaincopy

// 1.代替代理,RACSubject

// RAC方法:可以判断下某个方法有没有调用

// 只要self调用Selector就会产生一个信号

// rac_signalForSelector:监听某个对象调用某个方法

[[selfrac_signalForSelector:@selector(didReceiveMemoryWarning)]subscribeNext:^(idx) {

NSLog(@"控制器调用了didReceiveMemoryWarning");

}];

// 判断下redView有没有调用btnClick,就表示点击了按钮

[[_redViewrac_signalForSelector:@selector(btnClick:)]subscribeNext:^(idx) {

NSLog(@"点击了按钮");

}];

第2种:代替KVO

rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变

[objc]view plaincopy

[_redViewrac_observeKeyPath:@"name"options:NSKeyValueObservingOptionNewobserver:nilblock:^(idvalue,NSDictionary*change,BOOLcausedByDealloc,BOOLaffectedOnlyLastComponent) {

// 只要监听的属性一改变调用

NSLog(@"%@",_redView.name);

}];

// KVO:第二种,只要对象的值改变,就会产生信号,订阅信号

[[_redViewrac_valuesForKeyPath:@"name"observer:nil]subscribeNext:^(idx) {

}];

第3种:监听事件

rac_signalForControlEvents:用于监听某个事件

[objc]view plaincopy

//  只要按钮产生这个事件,就会产生一个信号

[[_btnrac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(idx) {

NSLog(@"按钮被点击%@",x);

}];

_btn.rac_command= [[RACCommandalloc]initWithSignalBlock:^RACSignal*(idinput) {

NSLog(@"按钮点击");

return[RACSignalempty];

}];

第4种:代替通知

rac_addObserverForName:用于监听某个通知

[objc]view plaincopy

[[[NSNotificationCenterdefaultCenter]rac_addObserverForName:UIKeyboardWillShowNotificationobject:nil]subscribeNext:^(idx) {

NSLog(@"%@",x);

}];

第5种:监听文本框文字改变

rac_textSignal:只要文本框发出改变就会发出这个信号

[objc]view plaincopy

[_textField.rac_textSignalsubscribeNext:^(idx) {

// x:文本框的文字

NSLog(@"%@",x);

}];

第6种:处理当界面有多次请求时,需要都获取到数据时,才能展示界面

rac_liftSelector:withSignalsFromArray:Signals:当传入的Signals(信号数组),

每一个signal都至少sendNext过一次,就会去触发第一个selector参数的方法

[objc]view plaincopy

RACSignal*requestHot = [RACSignalcreateSignal:^RACDisposable*(id subscriber) {

NSLog(@"请求最热商品");

[subscribersendNext:@"获取最热商品"];

returnnil;

}];

RACSignal*requestNew = [RACSignalcreateSignal:^RACDisposable*(id subscriber) {

NSLog(@"请求最新商品");

//        [subscriber sendNext:@"获取最新商品"];

returnnil;

}];

// Selector调用:当所有信号都发送数据的时候调用

// 数组存放信号

// Selector注意点:参数根据数组元素决定

// Selector方法参数类型,就是信号传递出来数据

[selfrac_liftSelector:@selector(updateUI:data2:)withSignalsFromArray:@[requestHot,requestNew]];

}

// 只要两个请求都请求完成的时候才会调用

- (void)updateUI:(NSString*)data1data2:(NSString*)data2

{

NSLog(@"%@ %@",data1,data2);

}

2.ReactiveCocoa常见宏

第一种

RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某个属性绑定

[objc]view plaincopy

// 给某个对象的某个属性绑定一个信号,只要产生信号,就会把信号的内容给对象的属性赋值

// 给label的text属性绑定一个信号

RAC(_label,text) = _texfField.rac_textSignal;

第二种

RACObserve(self, name):监听某个对象的某个属性,返回的是信号

[objc]view plaincopy

// 观察某个对象某个属性

[RACObserve(self, name)subscribeNext:^(idx) {

NSLog(@"%@",x);

}];

第三种

@weakify(Obj)和@strongify(Obj),一般两个都是配套使用,解决循环引用问题

第四种

RACTuplePack:把数据包装成RACTuple(元组类)

[objc]view plaincopy

// RACTuplePack:快速把一些数据包装成元组类

RACTuple*tuple = RACTuplePack(@"123",@1);

第五种

RACTupleUnpack:把RACTuple(元组类)解包成对应的数据

[objc]view plaincopy

// 参数:需要解析生成出来变量名

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的使用

[objc]view plaincopy

RACSignal*bindSignal = [_textField.rac_textSignalbind:^RACStreamBindBlock{

// block调用时刻:只要一个信号被绑定就会调用.表示信号绑定完成

NSLog(@"源信号被绑定");

return^RACStream*(idvalue,BOOLBOOL*stop){

// RACStreamBindBlock什么时候调用:每次源信号发出内容,就会调用这个block

// value:源信号发出的内容

NSLog(@"源信号发出的内容:%@",value);

// RACStreamBindBlock作用:在这个block处理源信号的内容

value = [NSStringstringWithFormat:@"xmg%@",value];

// block返回值:信号(把处理完的值包装成一个信号,返回出去)

// 创建一个信号,并且这个信号的传递的值是我们处理完的值,value

return[RACReturnSignalreturn:value];

};

}];

// 订阅绑定信号,不在是源信号

[bindSignalsubscribeNext:^(idx) {

NSLog(@"%@",x);

}];

// 执行流程

/*

1.文字改变源信号

2.绑定源信号,[_textField.rac_textSignal bind]

* 调用bind返回绑定好的信号,didSubscribe

3.订阅绑定信号

* 创建订阅者

* 调用绑定信号的didSubscribe

4.执行绑定信号didSubscribe

5.执行bind方法传入的block

6.订阅源信号

7.只要源信号一发出内容,就会调用id signal = bindingBlock(x, &stop);

* signal:把值处理完的信号

*/

ReactiveCocoa操作方法之映射(flattenMap,Map)

flattenMap:信号中信号,signalOfSignals

[objc]view plaincopy

[[_textField.rac_textSignalflattenMap:^RACStream*(idvalue) {

// value:源信号的内容

value = [NSStringstringWithFormat:@"xmg%@",value];

// 返回值:信号,把处理完的值包装成信号返回出去

return[RACReturnSignalreturn:value];

}]subscribeNext:^(idx) {

// 订阅[RACReturnSignal return:value发送值

// x:绑定信号的值

NSLog(@"%@",x);

}];

[objc]view plaincopy

map: 用于普通信号,信号发出普通值

[objc]view plaincopy

[[_textField.rac_textSignalmap:^id(idvalue) {

// value:源信号的内容

// 返回值,就是处理源信号的内容,直接返回

return[NSStringstringWithFormat:@"----xmg%@",value];

}]subscribeNext:^(idx) {

NSLog(@"%@",x);

}];

FlatternMap和Map的区别

1.FlatternMap中的Block返回信号。

2.Map中的Block返回对象。

3.开发中,如果信号发出的值不是信号,映射一般使用Map

4.开发中,如果信号发出的值是信号,映射一般使用FlatternMap。

ReactiveCocoa操作方法之组合

concat:按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号

[objc]view plaincopy

// concat:连接信号,有顺序的拼接,一定要等第一个信号完成的时候,第二个信号才会被激活

RACSubject*signalA = [RACSubjectsubject];

RACSubject*signalB = [RACSubjectsubject];

// 组合信号

RACSignal*signals = [signalAconcat:signalB];

// 订阅组合信号

[signalssubscribeNext:^(idx) {

NSLog(@"%@",x);

}];

// 发送数据

[signalAsendNext:@1];

[signalAsendCompleted];

[signalBsendNext:@2];

then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号

[objc]view plaincopy

RACSubject*signalA = [RACSubjectsubject];

RACSubject*signalB = [RACSubjectsubject];

// 组合

RACSignal*signals = [signalAthen:^RACSignal*{

returnsignalB;

}];

[signalssubscribeNext:^(idx) {

NSLog(@"%@",x);

}];

[signalAsendNext:@1];

[signalAsendCompleted];

[signalBsendNext:@2];

then跟concat区别:监听不到第一个信号的值,共同点都是必须第一个信号完成,第二个信号才会激活

merge: 把多个信号合并为一个信号,任何一个信号有新值的时候就会调用

[objc]view plaincopy

// merge:合并,任何一个信号只要发送值,就能订阅

RACSubject*signalA = [RACSubjectsubject];

RACSubject*signalB = [RACSubjectsubject];

RACSignal*signals = [signalAmerge:signalB];

[signalssubscribeNext:^(idx) {

NSLog(@"%@",x);

}];

[signalAsendNext:@1];

[signalBsendNext:@2];

[signalBsendNext:@3];

zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,

并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件

[objc]view plaincopy

RACSubject*signalA = [RACSubjectsubject];

RACSubject*signalB = [RACSubjectsubject];

RACSignal*signals = [signalAzipWith:signalB];

[signalssubscribeNext:^(idx) {

NSLog(@"%@",x);

}];

// zipWith:当两个信号都发出内容的时候,才能被订阅到

[signalAsendNext:@1];

[signalBsendNext:@2];

[signalBsendNext:@3];

[signalAsendNext:@4];

combineLatest:将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都

有过一次sendNext,才会触发合并的信号

[objc]view plaincopy

// 第一个参数:就是存放需要合并信号

[[RACSignalcombineLatest:@[_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= [xboolValue];

NSLog(@"%@",x);

}];

reduce聚合:用于信号发出的内容是元组,把信号发出元组的值聚合成一个值

[objc]view plaincopy

RACSignal*signalA = [RACSignalcreateSignal:^RACDisposable*(id subscriber) {

[subscribersendNext:@1];

returnnil;

}];

RACSignal*signalB = [RACSignalcreateSignal:^RACDisposable*(id subscriber) {

[subscribersendNext:@2];

returnnil;

}];

// 聚合

// 常见的用法,(先组合在聚合)。combineLatest:(id)signals reduce:(id (^)())reduceBlock

// reduce中的block简介:

// reduceblcok中的参数,有多少信号组合,reduceblcok就有多少参数,每个参数就是之前信号发出的内容

// reduceblcok的返回值:聚合信号之后的内容。

CSignal*reduceSignal = [RACSignalcombineLatest:@[signalA,signalB]reduce:^id(NSNumber*num1,NSNumber*num2){

return[NSStringstringWithFormat:@"%@ %@",num1,num2];

];

[reduceSignalsubscribeNext:^(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):处理展示的业务逻辑,包括按钮的点击,数据的请求和解析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容