我們平常所常用到的響應(yīng)式編程有哪些:代理,通知骤宣,KVO玄叠,Block回調(diào)祸穷,Target,監(jiān)聽事件等
通過RAC我們可以更加簡(jiǎn)單的實(shí)現(xiàn)事件的方法,降低了代碼的耦合度停蕉,更方便管理
RAC的優(yōu)點(diǎn):減少代碼量愕鼓,可靈活使用
RAC常用的幾種用法:
KVO、textFiled慧起、button - taget - event菇晃、delegate、通知蚓挤、代替某個(gè)方法
RAC常用的高級(jí)用法:
過濾:filter谋旦、ignore、distinctUntilChanged屈尼、take册着、takeLast、takeUntil脾歧、takeWhileBlock甲捏、skip、switchToLatest
秩序:doNext鞭执、 docompleted
時(shí)間:retry司顿、interval芒粹、delay
重復(fù):retry、replay大溜、throttle
其他方法:startWith
RAC的重要概念:
RACSignal化漆、RACSubscriber、RACSubject
集成:
Objective-C:pod 'ReactiveCocoa', '2.1.8'
Swift:https://github.com/ReactiveCocoa
RAC: 信號(hào) 面向信號(hào)開發(fā)G辗堋座云!
1.創(chuàng)建信號(hào)!付材!
RACSubject *subject = [RACSubject subject];
2.誰(shuí)對(duì)信號(hào)感興趣朦拖,誰(shuí)訂閱信號(hào)(訂閱者)
[subject subscribeNext:^(id x) {
NSLog(@"%@",x);//Hello RAC!!
}];
3.我發(fā)送信號(hào)
[subject sendNext:@"Hello RAC!!"];
代理
常用方法
1.定義一個(gè)方法
2.定義協(xié)議方法
3.定義一個(gè)代理屬性(遵守這個(gè)協(xié)議)
4.當(dāng)發(fā)生一些事情,我看看代理屬性有沒有值
5.看看代理有沒有響應(yīng)我的方法厌衔!
使用代理
1.設(shè)置代理
2.遵守協(xié)議
3.實(shí)現(xiàn)方法
//HKView頁(yè)面
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
-(void)btnClick:(UIButton *)send
{
點(diǎn)擊事件的處理過程
}
RAC方法
[[self.HkView rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(id x) {
點(diǎn)擊事件的處理過程
}];
代理傳值
//傳值頁(yè)面
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
-(void)btnClick:(UIButton *)send
{
[self sendContent:@"今天真開心h档邸!"];
}
-(void)sendContent:(id)objc
{
//可以什么都不做
}
//數(shù)據(jù)顯示和處理頁(yè)面
[[self.HkView rac_signalForSelector:@selector(sendContent:)]subscribeNext:^(id x) {
NSLog(@"%@",x);//今天真開心
}];
KVO
監(jiān)聽view的frame的變化
平時(shí)寫法
[self.hKView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
NSLog(@"觀察到了");
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
self.hKView.frame = CGRectMake(100, 100, 50, 50);
}
其他實(shí)例
// RACObserve(TARGET, KEYPATH):KVO富寿,監(jiān)聽某個(gè)對(duì)象的屬性睬隶,返回的是信號(hào)。
第一步:[self NotificationCenter];
第二步: [RACObserve(self.tabelView1, backgroundColor) subscribeNext:^(id _Nullable x) {
NSLog(@"self.view換了新背景顏色:%@",x);
}];
第三步:-(void)NotificationCenter
{
self.tabelView1.backgroundColor = [UIColor orangeColor];
}
[RACObserve(_tabelView1, contentOffset)subscribeNext:^(id x) {
//監(jiān)聽scrollview的滑動(dòng)
NSLog(@"success:%@",x);
}];
//五秒后執(zhí)行一次,延時(shí)執(zhí)行
[[RACScheduler mainThreadScheduler]afterDelay:5 schedule:^{
NSLog(@"五秒后執(zhí)行一次");
self.tabelView1.backgroundColor = [UIColor redColor];
}];
//每隔兩秒執(zhí)行一次
//這里要加takeUntil條件限制一下否則當(dāng)控制器pop后依舊會(huì)執(zhí)行
[[[RACSignal interval:2 onScheduler:[RACScheduler mainThreadScheduler]] takeUntil:self.rac_willDeallocSignal ] subscribeNext:^(id x) {
NSLog(@"每?jī)擅雸?zhí)行一次");
}];
}
RAC寫法
用來給某個(gè)對(duì)象的某個(gè)屬性綁定信號(hào)页徐,只要產(chǎn)生信號(hào)內(nèi)容理疙,就會(huì)將內(nèi)容賦值給屬性
//方法1:
[[self.hKView rac_valuesAndChangesForKeyPath:@"frame" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld observer:nil ]subscribeNext:^(id _Nullable x) {
NSLog(@"RAC觀察到了");
}];
//方法2:
[[self.hKView rac_valuesForKeyPath:@"frame" observer:self]subscribeNext:^(id _Nullable x) {
NSLog(@"RAC觀察到了");
}];
//方法3:
[RACObserve(self.hKView, frame) subscribeNext:^(id _Nullable x) {
NSLog(@"RAC觀察到了");
}];
最大的好處是:當(dāng)需要觀察某個(gè)對(duì)象的某些屬性時(shí),簡(jiǎn)化了代碼泞坦,使代碼更好維護(hù)和閱讀
監(jiān)聽事件
常用寫法
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
-(void)btnClick:(UIButton *)send
{
NSLog(@"今天真開心!砖顷!");
}
RAC寫法
//監(jiān)聽按鈕的點(diǎn)擊事件
[[btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
NSLog(@"今天真開心7∷!");
}];
通知
RAC通知傳值
//RAC通知
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 在某個(gè)頁(yè)面中我們需要發(fā)出通知滤蝠,發(fā)送名為postdata的通知并傳送一個(gè)數(shù)組dataArray
NSMutableArray *dataArray = [[NSMutableArray alloc] initWithObjects:@"1", @"2", @"3", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"postData" object:dataArray];
}
//調(diào)用鍵盤的通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
//可處理鍵盤彈出時(shí)頁(yè)面布局問題等
}];
UITextFiled
監(jiān)聽textFiled的輸入
文本框?qū)崟r(shí)的監(jiān)聽
[self.numTextF.rac_textSignal subscribeNext:^(NSString *x) {
NSLog(@"文本框輸入的內(nèi)容:%@" ,x);
}];
[self.nameTextF.rac_newTextChannel subscribeNext:^(id _Nullable x) {
NSLog(@"輸出什么:%@",x);
}];
[[self.nameTextF rac_inputTextSignal]subscribeNext:^(id x) {
NSLog(@"打印2:%@",x);
}];
//RAC的實(shí)時(shí)賦值
RAC(_labe1, text) = _numTextF.rac_textSignal;
textFiled數(shù)字輸入監(jiān)聽
[self.numTextF.rac_textSignal subscribeNext:^(NSString *x) {
static NSInteger const maxIntegerLength=8;//最大整數(shù)位
static NSInteger const maxFloatLength=2;//最大精確到小數(shù)位
if (x.length) {
//第一個(gè)字符處理
//第一個(gè)字符為0,且長(zhǎng)度>1時(shí)
if ([[x substringWithRange:NSMakeRange(0, 1)] isEqualToString:@"0"]) {
if (x.length>1) {
if ([[x substringWithRange:NSMakeRange(1, 1)] isEqualToString:@"0"]) {
//如果第二個(gè)字符還是0,即"00",則無(wú)效,改為"0"
self.numTextF.text=@"0";
}else if (![[x substringWithRange:NSMakeRange(1, 1)] isEqualToString:@"."]){
//如果第二個(gè)字符不是".",比如"03",清除首位的"0"
self.numTextF.text=[x substringFromIndex:1];
}
}
}
//第一個(gè)字符為"."時(shí),改為"0."
else if ([[x substringWithRange:NSMakeRange(0, 1)] isEqualToString:@"."]){
self.numTextF.text=@"0.";
}
//2個(gè)以上字符的處理
NSRange pointRange = [x rangeOfString:@"."];
NSRange pointsRange = [x rangeOfString:@".."];
if (pointsRange.length>0) {
//含有2個(gè)小數(shù)點(diǎn)
self.numTextF.text=[x substringToIndex:x.length-1];
}
else if (pointRange.length>0){
//含有1個(gè)小數(shù)點(diǎn)時(shí),并且已經(jīng)輸入了數(shù)字,則不能再次輸入小數(shù)點(diǎn)
if ((pointRange.location!=x.length-1) && ([[x substringFromIndex:x.length-1]isEqualToString:@"."])) {
self.numTextF.text=[x substringToIndex:x.length-1];
}
if (pointRange.location+maxFloatLength<x.length) {
//輸入位數(shù)超出精確度限制,進(jìn)行截取
self.numTextF.text=[x substringToIndex:pointRange.location+maxFloatLength+1];
}
}
else{
if (x.length>maxIntegerLength) {
self.numTextF.text=[x substringToIndex:maxIntegerLength];
}
}
}
}];
監(jiān)聽輸入字體個(gè)數(shù)的簡(jiǎn)單處理
//監(jiān)聽輸入字體個(gè)數(shù)
NSInteger maxLenght = 10;
[[self.nameTextF.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
return value.length > maxLenght;
}] subscribeNext:^(NSString * _Nullable x) {
// NSLog(@"最多輸入10個(gè)文字");
self.nameTextF.text = [self.nameTextF.text substringToIndex:maxLenght];
}];
未完待續(xù)...