1.ReactiveCocoa開發(fā)中常見用法有哪些恭取?
第1種:代替代理
rac_signalForSelector:用于替代代理
[objc]view plaincopy
//?1.代替代理,RACSubject
//?RAC方法:可以判斷下某個方法有沒有調(diào)用
//?只要self調(diào)用Selector就會產(chǎn)生一個信號
//?rac_signalForSelector:監(jiān)聽某個對象調(diào)用某個方法
[[selfrac_signalForSelector:@selector(didReceiveMemoryWarning)]subscribeNext:^(idx)?{
NSLog(@"控制器調(diào)用了didReceiveMemoryWarning");
}];
//?判斷下redView有沒有調(diào)用btnClick,就表示點擊了按鈕
[[_redViewrac_signalForSelector:@selector(btnClick:)]subscribeNext:^(idx)?{
NSLog(@"點擊了按鈕");
}];
第2種:代替KVO
rac_valuesAndChangesForKeyPath:用于監(jiān)聽某個對象的屬性改變
[objc]view plaincopy
[_redViewrac_observeKeyPath:@"name"options:NSKeyValueObservingOptionNewobserver:nilblock:^(idvalue,NSDictionary*change,BOOLcausedByDealloc,BOOLaffectedOnlyLastComponent)?{
//?只要監(jiān)聽的屬性一改變調(diào)用
NSLog(@"%@",_redView.name);
}];
//?KVO:第二種,只要對象的值改變,就會產(chǎn)生信號,訂閱信號
[[_redViewrac_valuesForKeyPath:@"name"observer:nil]subscribeNext:^(idx)?{
}];
第3種:監(jiān)聽事件
rac_signalForControlEvents:用于監(jiān)聽某個事件
[objc]view plaincopy
//??只要按鈕產(chǎn)生這個事件,就會產(chǎn)生一個信號
[[_btnrac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(idx)?{
NSLog(@"按鈕被點擊%@",x);
}];
_btn.rac_command=?[[RACCommandalloc]initWithSignalBlock:^RACSignal*(idinput)?{
NSLog(@"按鈕點擊");
return[RACSignalempty];
}];
第4種:代替通知
rac_addObserverForName:用于監(jiān)聽某個通知
[objc]view plaincopy
[[[NSNotificationCenterdefaultCenter]rac_addObserverForName:UIKeyboardWillShowNotificationobject:nil]subscribeNext:^(idx)?{
NSLog(@"%@",x);
}];
第5種:監(jiān)聽文本框文字改變
rac_textSignal:只要文本框發(fā)出改變就會發(fā)出這個信號
[objc]view plaincopy
[_textField.rac_textSignalsubscribeNext:^(idx)?{
//?x:文本框的文字
NSLog(@"%@",x);
}];
第6種:處理當(dāng)界面有多次請求時傻昙,需要都獲取到數(shù)據(jù)時,才能展示界面
rac_liftSelector:withSignalsFromArray:Signals:當(dāng)傳入的Signals(信號數(shù)組)规丽,
每一個signal都至少sendNext過一次松捉,就會去觸發(fā)第一個selector參數(shù)的方法
[objc]view plaincopy
RACSignal*requestHot?=?[RACSignalcreateSignal:^RACDisposable*(id?subscriber)?{
NSLog(@"請求最熱商品");
[subscribersendNext:@"獲取最熱商品"];
returnnil;
}];
RACSignal*requestNew?=?[RACSignalcreateSignal:^RACDisposable*(id?subscriber)?{
NSLog(@"請求最新商品");
//????????[subscriber?sendNext:@"獲取最新商品"];
returnnil;
}];
//?Selector調(diào)用:當(dāng)所有信號都發(fā)送數(shù)據(jù)的時候調(diào)用
//?數(shù)組存放信號
//?Selector注意點:參數(shù)根據(jù)數(shù)組元素決定
//?Selector方法參數(shù)類型,就是信號傳遞出來數(shù)據(jù)
[selfrac_liftSelector:@selector(updateUI:data2:)withSignalsFromArray:@[requestHot,requestNew]];
}
//?只要兩個請求都請求完成的時候才會調(diào)用
-?(void)updateUI:(NSString*)data1data2:(NSString*)data2
{
NSLog(@"%@?%@",data1,data2);
}
2.ReactiveCocoa常見宏
第一種
RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于給某個對象的某個屬性綁定
[objc]view plaincopy
//?給某個對象的某個屬性綁定一個信號,只要產(chǎn)生信號,就會把信號的內(nèi)容給對象的屬性賦值
//?給label的text屬性綁定一個信號
RAC(_label,text)?=?_texfField.rac_textSignal;
第二種
RACObserve(self, name):監(jiān)聽某個對象的某個屬性,返回的是信號
[objc]view plaincopy
//?觀察某個對象某個屬性
[RACObserve(self,?name)subscribeNext:^(idx)?{
NSLog(@"%@",x);
}];
第三種
@weakify(Obj)和@strongify(Obj),一般兩個都是配套使用,解決循環(huán)引用問題
第四種
RACTuplePack:把數(shù)據(jù)包裝成RACTuple(元組類)
[objc]view plaincopy
//?RACTuplePack:快速把一些數(shù)據(jù)包裝成元組類
RACTuple*tuple?=?RACTuplePack(@"123",@1);
第五種
RACTupleUnpack:把RACTuple(元組類)解包成對應(yīng)的數(shù)據(jù)
[objc]view plaincopy
//?參數(shù):需要解析生成出來變量名
RACTupleUnpack(NSString*str,NSNumber*num)?=?tuple;
NSLog(@"%@?%@",str,num);
3.ReactiveCocoa常見操作方法
ReactiveCocoa操作原理
所有的信號(RACSignal)都可以進(jìn)行操作處理是越,因為所有操作方法都定義在RACStream.h中蔑歌,因此只要繼承RACStream就有了操作處理方法
ReactiveCocoa操作思想
運用的是Hook(鉤子)思想震叙,Hook是一種用于改變API(應(yīng)用程序編程接口:方法)執(zhí)行結(jié)果的技術(shù). Hook用處:截獲API調(diào)用的技術(shù)掀鹅。 Hook原理:在每次調(diào)用一個API返回結(jié)果之前,先執(zhí)行你自己的方法媒楼,改變結(jié)果的輸出
ReactiveCocoa核心方法bind
ReactiveCocoa操作的核心方法是bind(綁定),而且RAC中核心開發(fā)方式乐尊,也是綁定,之前的開發(fā)方式是賦值划址,而用RAC開發(fā)扔嵌,應(yīng)該把重心放在綁定,也就是可以在創(chuàng)建一個對象的時候夺颤,就綁定好以后想要做的事情痢缎,而不是等賦值之后在去做事情
核心方法bind的使用
[objc]view plaincopy
RACSignal*bindSignal?=?[_textField.rac_textSignalbind:^RACStreamBindBlock{
//?block調(diào)用時刻:只要一個信號被綁定就會調(diào)用.表示信號綁定完成
NSLog(@"源信號被綁定");
return^RACStream*(idvalue,BOOLBOOL*stop){
//?RACStreamBindBlock什么時候調(diào)用:每次源信號發(fā)出內(nèi)容,就會調(diào)用這個block
//?value:源信號發(fā)出的內(nèi)容
NSLog(@"源信號發(fā)出的內(nèi)容:%@",value);
//?RACStreamBindBlock作用:在這個block處理源信號的內(nèi)容
value?=?[NSStringstringWithFormat:@"xmg%@",value];
//?block返回值:信號(把處理完的值包裝成一個信號,返回出去)
//?創(chuàng)建一個信號,并且這個信號的傳遞的值是我們處理完的值,value
return[RACReturnSignalreturn:value];
};
}];
//?訂閱綁定信號,不在是源信號
[bindSignalsubscribeNext:^(idx)?{
NSLog(@"%@",x);
}];
//?執(zhí)行流程
/*
1.文字改變源信號
2.綁定源信號,[_textField.rac_textSignal?bind]
*?調(diào)用bind返回綁定好的信號,didSubscribe
3.訂閱綁定信號
*?創(chuàng)建訂閱者
*?調(diào)用綁定信號的didSubscribe
4.執(zhí)行綁定信號didSubscribe
5.執(zhí)行bind方法傳入的block
6.訂閱源信號
7.只要源信號一發(fā)出內(nèi)容,就會調(diào)用id?signal?=?bindingBlock(x,?&stop);
*?signal:把值處理完的信號
*/
ReactiveCocoa操作方法之映射(flattenMap,Map)
flattenMap:信號中信號,signalOfSignals
[objc]view plaincopy
[[_textField.rac_textSignalflattenMap:^RACStream*(idvalue)?{
//?value:源信號的內(nèi)容
value?=?[NSStringstringWithFormat:@"xmg%@",value];
//?返回值:信號,把處理完的值包裝成信號返回出去
return[RACReturnSignalreturn:value];
}]subscribeNext:^(idx)?{
//?訂閱[RACReturnSignal?return:value發(fā)送值
//?x:綁定信號的值
NSLog(@"%@",x);
}];
[objc]view plaincopy
map:?用于普通信號,信號發(fā)出普通值
[objc]view plaincopy
[[_textField.rac_textSignalmap:^id(idvalue)?{
//?value:源信號的內(nèi)容
//?返回值,就是處理源信號的內(nèi)容,直接返回
return[NSStringstringWithFormat:@"----xmg%@",value];
}]subscribeNext:^(idx)?{
NSLog(@"%@",x);
}];
FlatternMap和Map的區(qū)別
1.FlatternMap中的Block返回信號。
2.Map中的Block返回對象世澜。
3.開發(fā)中独旷,如果信號發(fā)出的值不是信號,映射一般使用Map
4.開發(fā)中寥裂,如果信號發(fā)出的值是信號嵌洼,映射一般使用FlatternMap。
ReactiveCocoa操作方法之組合
concat:按一定順序拼接信號封恰,當(dāng)多個信號發(fā)出的時候麻养,有順序的接收信號
[objc]view plaincopy
//?concat:連接信號,有順序的拼接,一定要等第一個信號完成的時候,第二個信號才會被激活
RACSubject*signalA?=?[RACSubjectsubject];
RACSubject*signalB?=?[RACSubjectsubject];
//?組合信號
RACSignal*signals?=?[signalAconcat:signalB];
//?訂閱組合信號
[signalssubscribeNext:^(idx)?{
NSLog(@"%@",x);
}];
//?發(fā)送數(shù)據(jù)
[signalAsendNext:@1];
[signalAsendCompleted];
[signalBsendNext:@2];
then:用于連接兩個信號,當(dāng)?shù)谝粋€信號完成诺舔,才會連接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區(qū)別:監(jiān)聽不到第一個信號的值,共同點都是必須第一個信號完成,第二個信號才會激活
merge: 把多個信號合并為一個信號回溺,任何一個信號有新值的時候就會調(diào)用
[objc]view plaincopy
//?merge:合并,任何一個信號只要發(fā)送值,就能訂閱
RACSubject*signalA?=?[RACSubjectsubject];
RACSubject*signalB?=?[RACSubjectsubject];
RACSignal*signals?=?[signalAmerge:signalB];
[signalssubscribeNext:^(idx)?{
NSLog(@"%@",x);
}];
[signalAsendNext:@1];
[signalBsendNext:@2];
[signalBsendNext:@3];
zipWith:把兩個信號壓縮成一個信號,只有當(dāng)兩個信號同時發(fā)出信號內(nèi)容時混萝,
并且把兩個信號的內(nèi)容合并成一個元組遗遵,才會觸發(fā)壓縮流的next事件
[objc]view plaincopy
RACSubject*signalA?=?[RACSubjectsubject];
RACSubject*signalB?=?[RACSubjectsubject];
RACSignal*signals?=?[signalAzipWith:signalB];
[signalssubscribeNext:^(idx)?{
NSLog(@"%@",x);
}];
//?zipWith:當(dāng)兩個信號都發(fā)出內(nèi)容的時候,才能被訂閱到
[signalAsendNext:@1];
[signalBsendNext:@2];
[signalBsendNext:@3];
[signalAsendNext:@4];
combineLatest:將多個信號合并起來,并且拿到各個信號的最新的值,必須每個合并的signal至少都
有過一次sendNext逸嘀,才會觸發(fā)合并的信號
[objc]view plaincopy
//?第一個參數(shù):就是存放需要合并信號
[[RACSignalcombineLatest:@[_textField1.rac_textSignal,_textField2.rac_textSignal]reduce:^id(NSString*str1,NSString*str2){
NSLog(@"%@?----?%@",str1,str2);
//?block:只要任意一個信號發(fā)出內(nèi)容,就會調(diào)用
//?block參數(shù)個數(shù):由信號決定
//?block參數(shù)類型:block的參數(shù)就是信號發(fā)出值
//?把兩個信號中的值聚合成哪個值
return@(str1.length&&?str2.length);
}]subscribeNext:^(idx)?{
_btn.enabled=?[xboolValue];
NSLog(@"%@",x);
}];
reduce聚合:用于信號發(fā)出的內(nèi)容是元組车要,把信號發(fā)出元組的值聚合成一個值
[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中的參數(shù)翼岁,有多少信號組合,reduceblcok就有多少參數(shù)司光,每個參數(shù)就是之前信號發(fā)出的內(nèi)容
//?reduceblcok的返回值:聚合信號之后的內(nèi)容琅坡。
CSignal*reduceSignal?=?[RACSignalcombineLatest:@[signalA,signalB]reduce:^id(NSNumber*num1,NSNumber*num2){
return[NSStringstringWithFormat:@"%@?%@",num1,num2];
];
[reduceSignalsubscribeNext:^(idx)?{
NSLog(@"%@",x);
}];
ReactiveCocoa操作方法之過濾
filter:過濾信號,使用它可以獲取滿足條件的信號
ignore:忽略完某些值的信號
distinctUntilChanged:當(dāng)上一次的值和當(dāng)前的值有明顯的變化就會發(fā)出信號残家,否則會被忽略掉
take:從開始一共取N次的信號
takeLast:取最后N次的信號,前提條件榆俺,訂閱者必須調(diào)用完成,因為只有完成,就知道總共有多少信號
takeUntil:(RACSignal *):獲取信號直到執(zhí)行完這個信號
skip:(NSUInteger):跳過幾個信號,不接受
switchToLatest:用于signalOfSignals(信號的信號)茴晋,有時候信號也會發(fā)出信號陪捷,會在signalOfSignals中,獲取signalOfSignals發(fā)送的最新信號
ReactiveCocoa操作方法之秩序
doNext: 執(zhí)行Next之前诺擅,會先執(zhí)行這個Block
doCompleted: 執(zhí)行sendCompleted之前市袖,會先執(zhí)行這個Block
ReactiveCocoa操作方法之線程
deliverOn: 內(nèi)容傳遞切換到制定線程中,副作用在原來線程中,把在創(chuàng)建信號時block中的代碼稱之為副作用
subscribeOn: 內(nèi)容傳遞和副作用都會切換到制定線程中
ReactiveCocoa操作方法之時間
timeout:超時烁涌,可以讓一個信號在一定的時間后苍碟,自動報錯
interval 定時:每隔一段時間發(fā)出信號
delay: 延遲發(fā)送next
ReactiveCocoa操作方法之重復(fù)
retry重試 :只要失敗,就會重新執(zhí)行創(chuàng)建信號中的block,直到成功
replay重放:當(dāng)一個信號被多次訂閱,反復(fù)播放內(nèi)容
throttle節(jié)流:當(dāng)某個信號發(fā)送比較頻繁時撮执,可以使用節(jié)流微峰,在某一段時間不發(fā)送信號內(nèi)容,過了一段時間獲取信號的最新內(nèi)容發(fā)出
4.學(xué)習(xí)MVVM架構(gòu)思想
(1)程序為什么要架構(gòu)二打?
便于程序員開發(fā)和維護(hù)代碼
(2)常見的架構(gòu)思想有哪些县忌?
MVC ---- M:模型 V:視圖 C:控制器)
MVVM ----M:模型 V:視圖+控制器 VM:視圖模型
MVCS ---- M:模型 V:視圖 C:控制器 S:服務(wù)類
VIPER ---- V:視圖 I:交互器 P:展示器 E:實體 R:路由
(3)MVVM思想
模型(M):保存視圖數(shù)據(jù)
視圖+控制器(V):展示內(nèi)容 + 如何展示
視圖模型(VM):處理展示的業(yè)務(wù)邏輯,包括按鈕的點擊继效,數(shù)據(jù)的請求和解析