RAC整理

RAC常用的方法,搭配@weakify(self); @weakify(self);

    1. 通知
# RAC中的通知不需要手动remove observer,其内部已经实现
  @weakify(self);
 [[[NSNotificationCenter defaultCenter] rac_addObserverForName:kNotificationName object:nil] 
  subscribeNext:^(NSNotification * _Nullable x) {
        @strongify(self);

    }];

    1. control
# control的通用方法
 @weakify(self);
 [[button rac_signalForControlEvents:UIControlEventTouchUpOutside] subscribeNext:^(__kindof UIControl * _Nullable  x) {
        @strongify(self);

    }];
# 监听textfild的UIControlEventEditingChanged事件
# 方式一:
[[textFild rac_signalForControlEvents:UIControlEventEditingChanged] subscribeNext:^(__kindof UIControl * _Nullable  x){
    NSLog(@"change");
}];
# 方式二:
[[self.textFild rac_textSignal] subscribeNext:^(NSString *x) {
    NSLog(@"%@",x);
}];
//这样就是每次改变TextFild都输出改变后的结果
    1. Gesturer
# 再比如给我们的某个label添加一个手势动作,我们也可以用简单的RAC代码完成
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
[[tap rac_gestureSignal] subscribeNext:^(__kindof   UIGestureRecognizer  * _Nullable x) {
    NSLog(@"tap");
}];
[self.view addGestureRecognizer:tap];
    1. 代理

用RAC写代理是有局限的,它只能实现返回值为void的代理方法,RAC为我们提供了一个rac_signalForSelector: fromProtoc:方法帮我们实现代理

# alert方式一:
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"RAC" message:@"RAC TEST" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"other", nil];
[[self rac_signalForSelector:@selector(alertView:clickedButtonAtIndex:) fromProtocol:@protocol(UIAlertViewDelegate)] subscribeNext:^(RACTuple *tuple) {
 # tuple封装了方法的参数,可以取出参数对应的值
    NSLog(@"%@",tuple.first);
 #可以看出tuple.second是点击Item的Index
    NSLog(@"%@",tuple.second);
    NSLog(@"%@",tuple.third);
}];
[alertView show];
#查看RACTuple
@interface RACTuple : NSObject <NSCoding, NSCopying, NSFastEnumeration>

@property (nonatomic, readonly) NSUInteger count;

/// These properties all return the object at that index or nil if the number of 
/// objects is less than the index.
@property (nonatomic, readonly, nullable) id first;
@property (nonatomic, readonly, nullable) id second;
@property (nonatomic, readonly, nullable) id third;
@property (nonatomic, readonly, nullable) id fourth;
@property (nonatomic, readonly, nullable) id fifth;
@property (nonatomic, readonly, nullable) id last;

2021-03-19 12:24:29.114 RACStudyTest[5003:388870] <UIAlertView: 0x7ff260c90c70; frame = (0 0; 0 0); layer = <CALayer: 0x7ff260c91030>>
2021-03-19 12:24:29.115 RACStudyTest[5003:388870] 1
2021-03-19 12:24:29.115 RACStudyTest[5003:388870] (null)
# alert方式二
[[alertView rac_buttonClickedSignal] subscribeNext:^(id x) {
#  这里的x是点击Item的Index
    NSLog(@"%@",x);
}];
    1. kvo

RAC中得KVO大部分都是宏定义,所以代码异常简洁,简单来说就是 RACObserve(TARGET, KEYPATH)这种形式,TARGET是监听目标,KEYPATH是要观察的属性值


 @weakify(self);
[RACObserve(object, propertyChanged) subscribeNext:^(id propertyChangedValue) {
        @strongify(self);    

}];
  [[RACSignal combineLatest:@[RACObserve(self.messageViewController, unReadMessageCount),RACObserve(self.friendsVc, unReadMessageCount),RACObserve(self, unReadSystemCount)]] subscribeNext:^(RACTuple *x) {
        @strongify(self);
        NSInteger first = ((NSNumber *)x.first).integerValue;
        NSInteger second = ((NSNumber *)x.second).integerValue;
        NSInteger third = ((NSNumber *)x.third).integerValue;
        JHTabBarController *tabbarVC = (JHTabBarController *)self.tabBarController;
        [tabbarVC.customTabBar hideBadgeOnItemIndex:3];//隐藏未读小红点
        if (first>0||second>0||third>0) {
            [tabbarVC.customTabBar showBadgeOnItemIndex:3 value:(first+second+third)];//显示未读小红点
        }
    }];

RACSignal 封装请求

- (RACSignal *)sendShareMessageWithModel:(JH_ChatRoomBaseModel *)messageModel {
    
    @weakify(self);
    
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        
        @strongify(self);
        
        [self addMessageModelToDatabase:messageModel];
        
        //通过Socket向服务器发送消息
        [self sendMessageToServerWithModel:messageModel];
        // 给订阅者发送消息
        [subscriber sendNext:@(YES)];
        [subscriber sendCompleted];
        
        return nil;
    }];
}

RAC相关类

RACSignal的使用

   // 创建一个信号
   RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
       
       NSLog(@"创建一个信号");
       
       // 发送信号
       [subscriber sendNext:@"发送一个信号"];
       
       return nil;
   }];
   
   // 订阅一个信号
   [signal subscribeNext:^(id  _Nullable x) {
       
       NSLog(@"订阅一个信号");
       NSLog(@"订阅到的: %@", x);
   }];
2017-07-22 17:37:09.294 RAC[66282:12633516] 创建一个信号
2017-07-22 17:37:09.295 RAC[66282:12633516] 订阅一个信号
2017-07-22 17:37:09.295 RAC[66282:12633516] 订阅到的: 发送一个信号

sendNext就把内容传递到了Next的block中了

UITextField+RACSignalSupport.h

#import <UIKit/UIKit.h>

@class RACChannelTerminal<ValueType>;
@class RACSignal<__covariant ValueType>;

NS_ASSUME_NONNULL_BEGIN
# 
@interface UITextField (RACSignalSupport)
#  
- (RACSignal<NSString *> *)rac_textSignal;
# 用于双向绑定
- (RACChannelTerminal<NSString *> *)rac_newTextChannel;

@end

NS_ASSUME_NONNULL_END

rac_textSignal

UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];
    
    textField.center          = self.view.center;
    textField.backgroundColor = [UIColor yellowColor];
    
    [[textField
        rac_textSignal]
        subscribeNext:^(NSString * _Nullable x) {
            
            NSLog(@"%@", x);
        }];
    
    [self.view addSubview:textField];

2017-07-23 22:55:45.686 RAC[70205:14118946] 1
2017-07-23 22:55:46.139 RAC[70205:14118946] 11
2017-07-23 22:55:46.798 RAC[70205:14118946] 111

rac_newTextChannel

@interface RACChannelTerminal<ValueType> : RACSignal<ValueType> <RACSubscriber>

- (instancetype)init __attribute__((unavailable("Instantiate a RACChannel instead")));

// Redeclaration of the RACSubscriber method. Made in order to specify a generic type.
- (void)sendNext:(nullable ValueType)value;

@end
#rac_newTextChannel效果跟rac_textSignal一样, 那么它有什么特别的用法呢?
[[textField
        rac_newTextChannel]
        subscribeNext:^(NSString * _Nullable x) {
            
            NSLog(@"%@", x);
        }];
#rac_newTextChannel双向绑定
    UITextField *textFieldA = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];
    
    textFieldA.center          = self.view.center;
    textFieldA.backgroundColor = [UIColor yellowColor];
    
    [self.view addSubview:textFieldA];
    
    UITextField *textFieldB = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];
    
    textFieldB.center          = CGPointMake(self.view.center.x, self.view.center.y + 50);
    textFieldB.backgroundColor = [UIColor yellowColor];
    
    [self.view addSubview:textFieldB];
    
    RACChannelTerminal *terminalA = [textFieldA rac_newTextChannel];
    RACChannelTerminal *terminalB = [textFieldB rac_newTextChannel];
    
    [terminalA subscribe:terminalB];
    [terminalB subscribe:terminalA];

#运行可以看到, 改变textFieldA的值textFieldB的值也会跟着改变, 反过来也一样.

#这里如果要实现双向绑定, 其实还有一个简单的方法:
RACChannelTo(textFieldA, text) = RACChannelTo(textFieldB, text);

如果我们不仅仅想让两个绑定对象之间的值简单的相等而已呢? 比如textFieldA的值是123的时候textFieldB的值要为321要怎么处理呢?
这里我们先说一个一会用到的方法: map(映射)

map方法,将会创建一个和原来一模一样的信号,只不过新的信号传递的值变为了block(value)。

[[[textField
        rac_textSignal]
        map:^id _Nullable(NSString * _Nullable value) {
            
            if ([value isEqualToString:@"11"]) {
                
                return @"1";
            } else {
                
                return @"0";
            }
        }] subscribeNext:^(id  _Nullable x) {
            
            NSLog(@"%@", x);
        }];

运行看看, 当我们输入1, 会打印0, 输入11的时候会打印1, 这里就是把传递的值从textField的text转变成为我们的1 和 0;

那么要实现上面的123 到 321可以这样写:

    RACChannelTerminal *terminalA = [textFieldA rac_newTextChannel];
    RACChannelTerminal *terminalB = [textFieldB rac_newTextChannel];
    
    [[terminalA
        map:^id _Nullable(id  _Nullable value) {
            
            if ([value isEqualToString:@"123"]) {
                
                return @"321";
            }
            
            return value;
        }]
        subscribe:terminalB];

    [terminalB subscribe:terminalA];

大家可以自己运行看看效果, 当textFieldA输入123的时候textFieldB会变为321

 RAC(self.sureBtn, enabled) = [RACSignal combineLatest:@[self.phoneTF.rac_textSignal, self.codeTF.rac_textSignal] reduce:^id (NSString *phoneNumber, NSString *code){
        @strongify(self);
        if (phoneNumber.length==11 && code.length==6) {
            self.sureBtn.alpha = 1;
            return @(YES);
        } else {
            self.sureBtn.alpha = 0.6;
            return @(NO);
        }
    }];

UIActionSheet+RACSignalSupport.h

#import <UIKit/UIKit.h>

@class RACDelegateProxy;
@class RACSignal<__covariant ValueType>;

NS_ASSUME_NONNULL_BEGIN

@interface UIActionSheet (RACSignalSupport)

@property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy;

- (RACSignal<NSNumber *> *)rac_buttonClickedSignal;

@end

rac_buttonClickedSignal

UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"RAC ActionSheet" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"OK" otherButtonTitles:@"Other", nil];
    
    [[actionSheet
        rac_buttonClickedSignal]
     subscribeNext:^(NSNumber * _Nullable x) {
         
         NSLog(@"%@", x);
     }];
    
    [actionSheet showInView:self.view];
  #运行看看, x是actionSheet上按钮的编号, 我们拿到编号就可以做响应的事件处理了.

UIAlertView+RACSignalSupport.h

@interface UIAlertView (RACSignalSupport)

@property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy;


- (RACSignal<NSNumber *> *)rac_buttonClickedSignal;


- (RACSignal<NSNumber *> *)rac_willDismissSignal;

@end

NS_ASSUME_NONNULL_END
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"RAC" message:@"RAC Alert" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
    
    [[alert
        rac_buttonClickedSignal]
        subscribeNext:^(NSNumber * _Nullable x) {
            
            NSLog(@"click: x");
        }];
    
    [[alert
        rac_willDismissSignal]
        subscribeNext:^(NSNumber * _Nullable x) {
            
            NSLog(@"dismiss: %@", x);
        }];
    
    [alert show];

UIControl+RACSignalSupport.h

#import <UIKit/UIKit.h>

@class RACSignal<__covariant ValueType>;

NS_ASSUME_NONNULL_BEGIN

@interface UIControl (RACSignalSupport)

- (RACSignal<__kindof UIControl *> *)rac_signalForControlEvents:(UIControlEvents)controlEvents;

@end

NS_ASSUME_NONNULL_END
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    
    [button setFrame:CGRectMake(0, 0, 100, 35)];
    [button setCenter:self.view.center];
    [button setBackgroundColor:[UIColor yellowColor]];
    [button setTitle:@"按钮" forState:UIControlStateNormal];
    
    [[button
        rac_signalForControlEvents:UIControlEventTouchUpInside]
        subscribeNext:^(__kindof UIControl * _Nullable x) {
            
            NSLog(@"点击了按钮");
            x.backgroundColor = [UIColor redColor];
        }];
    
    [self.view addSubview:button];

UIDatePicker+RACSignalSupport.h

#import <UIKit/UIKit.h>

@class RACChannelTerminal<ValueType>;

NS_ASSUME_NONNULL_BEGIN

@interface UIDatePicker (RACSignalSupport)

- (RACChannelTerminal<NSDate *> *)rac_newDateChannelWithNilValue:(nullable NSDate *)nilValue;

@end

NS_ASSUME_NONNULL_END
UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 160)];
    datePicker.center = self.view.center;
    datePicker.backgroundColor = [UIColor redColor];
    
    [self.view addSubview:datePicker];
    
    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 180, 35)];
    textField.center = CGPointMake(self.view.center.x, self.view.center.y - 100);
    textField.backgroundColor = [UIColor yellowColor];
    
    [self.view addSubview:textField];
    
    
    RACChannelTerminal *datePickerTerminal = [datePicker rac_newDateChannelWithNilValue:[NSDate date]];
    RACChannelTerminal *textFieldTerminal  = [textField rac_newTextChannel];
    
    [[datePickerTerminal
        map:^id _Nullable(id  _Nullable value) {
            NSLog(@"%@", value);
            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
            return [dateFormatter stringFromDate:value];
        }]
        subscribe:textFieldTerminal];
截屏2021-03-19 下午2.46.31.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,313评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,369评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,916评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,333评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,425评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,481评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,491评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,268评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,719评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,004评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,179评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,832评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,510评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,153评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,402评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,045评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,071评论 2 352

推荐阅读更多精彩内容