之前講了RAC如何幫我們實(shí)現(xiàn)KVO / 代理 / 事件 / 通知

今天先不去分析它的核心代碼, 我們先看看ReactiveObjC庫(kù)里面一些特別的東西,  如果大家點(diǎn)開(kāi)ReactiveObjC目錄應(yīng)該會(huì)看到很多category, 今天我們先來(lái)看看這些

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

我們先從UITextView+RACSignalSupport.h開(kāi)始看

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

#import <UIKit/UIKit.h>@class RACDelegateProxy;@class RACSignal<__covariant ValueType>;

NS_ASSUME_NONNULL_BEGIN@interface UITextView (RACSignalSupport)

@property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy;- (RACSignal<NSString *> *)rac_textSignal;@end

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

這里有一個(gè)屬性跟一個(gè)方法,  

關(guān)于RACDelegateProxy這個(gè)類的用途大概是把初始化傳入的代理綁定或者添加給當(dāng)前正在處理的信號(hào)

給大家一個(gè)例子:

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

  <ReactiveObjC.h> <objc/runtime.h> ViewController ()<UITextViewDelegate>- (
    RACDelegateProxy *delegateProxy = [[RACDelegateProxy alloc] initWithProtocol:^(RACTuple **textView = [[UITextView alloc] initWithFrame:CGRectMake(, , , ==
    textView.        = (<UITextViewDelegate>

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

這個(gè)一般是RAC內(nèi)部使用, 我們比較少用. 另外也只能處理沒(méi)有返回值的代理方法

可以到UITextview+RACSignalSupport.m里面看看, 也是類似這樣用的

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

- (RACDelegateProxy *)rac_delegateProxy {
    RACDelegateProxy *proxy = objc_getAssociatedObject(self, _cmd);    if (proxy == nil) {
        proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UITextViewDelegate)];
        objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }    return proxy;
}

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

 

好了, 現(xiàn)在我們來(lái)使用下這個(gè)UITextView類別唯一的方法

- (RACSignal<NSString *> *)rac_textSignal;

大家可以看到, 這個(gè)方法會(huì)返回一個(gè)信號(hào) 我們可以對(duì)他訂閱, 試試看

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    textView.center          = self.view.center;
    textView.backgroundColor = [UIColor greenColor];

    [self.view addSubview:textView];

    [[textView
     rac_textSignal]
     subscribeNext:^(NSString * _Nullable x) {
         
         NSLog(@"%@", x);
     }];

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

運(yùn)行看看, 當(dāng)我們?cè)趖extView中輸入文字的時(shí)候會(huì)打印:

2017-07-23 22:41:42.841 RAC[70053:14036438] 12017-07-23 22:41:43.353 RAC[70053:14036438] 112017-07-23 22:41:44.031 RAC[70053:14036438] 111

所以這個(gè)x就是Textview的內(nèi)容了.

 

下面我們看看

UITextField+RACSignalSupport.h

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

#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;@endNS_ASSUME_NONNULL_END

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

這里有兩個(gè)方法, 我們先看第一個(gè)rac_textSignal

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

    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];

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

運(yùn)行看看, 我們輸入數(shù)字的時(shí)候會(huì)打印內(nèi)容:

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

然后我們看看另外一個(gè)方法

- (RACChannelTerminal<NSString *> *)rac_newTextChannel;

這里涉及到了一個(gè)類RACChannelTerminal, 我們點(diǎn)進(jìn)去看看這個(gè)類

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

@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

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

可以看到它是一個(gè)RACSignal的子類,  我們先調(diào)用看看這個(gè)方法

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

[[textField
        rac_newTextChannel]
        subscribeNext:^(NSString * _Nullable x) {
            
            NSLog(@"%@", x);
        }];

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

效果跟rac_textSignal一樣, 那么它有什么特別的用法呢

它的作用是做雙向綁定 關(guān)于什么是雙向綁定呢? 給大家一個(gè)簡(jiǎn)單的例子:

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

    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];

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

運(yùn)行可以看到, 改變textFieldA的值textFieldB的值也會(huì)跟著改變, 反過(guò)來(lái)也一樣.

這里如果要實(shí)現(xiàn)雙向綁定, 其實(shí)還有一個(gè)簡(jiǎn)單的方法:

RACChannelTo(textFieldA, text) = RACChannelTo(textFieldB, text);

大家可以試試看.

 

如果我們不僅僅想讓兩個(gè)綁定對(duì)象之間的值簡(jiǎn)單的相等而已呢? 比如textFieldA的值是123的時(shí)候textFieldB的值要為321要怎么處理呢?

這里我們先說(shuō)一個(gè)一會(huì)用到的方法: map

map方法,將會(huì)創(chuàng)建一個(gè)和原來(lái)一模一樣的信號(hào),只不過(guò)新的信號(hào)傳遞的值變?yōu)榱薭lock(value)。

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

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

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

運(yùn)行看看, 當(dāng)我們輸入1, 會(huì)打印0, 輸入11的時(shí)候會(huì)打印1, 這里就是把傳遞的值從textField的text轉(zhuǎn)變成為我們的1 和 0;

然后有個(gè)特別的地方, 加入我們知道傳遞的值的類型, 我們就可以直接把后面訂閱的block里面的參數(shù)類型直接改成我們知道的類型

例如把id改為NSString *運(yùn)行結(jié)果也是一樣的, 這個(gè)是RAC一個(gè)比較特別的地方

 

那么要實(shí)現(xiàn)上面的123 到 321可以這樣寫(xiě):

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

    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];

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

大家可以自己運(yùn)行看看效果, 當(dāng)textFieldA輸入123的時(shí)候textFieldB會(huì)變?yōu)?21

 

下面我們看看

UIActionSheet+RACSignalSupport.h

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

#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

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

rac_delegateProxy跟之前textview是一樣的用法這里開(kāi)始就不再解釋這類屬性了

我們直接試著使用rac_buttonClickedSignal

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

    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];

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

運(yùn)行看看, x是actionSheet上按鈕的編號(hào), 我們拿到編號(hào)就可以做響應(yīng)的事件處理了.

 

UIAlertView+RACSignalSupport.h

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

@interface UIAlertView (RACSignalSupport)

@property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy;- (RACSignal<NSNumber *> *)rac_buttonClickedSignal;- (RACSignal<NSNumber *> *)rac_willDismissSignal;@endNS_ASSUME_NONNULL_END

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

它有兩個(gè)方法, 一個(gè)是點(diǎn)擊的時(shí)候用, 一個(gè)是dismiss的時(shí)候用

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

    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];

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

 

UIControl+RACSignalSupport.h

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

#import <UIKit/UIKit.h>@class RACSignal<__covariant ValueType>;

NS_ASSUME_NONNULL_BEGIN@interface UIControl (RACSignalSupport)- (RACSignal<__kindof UIControl *> *)rac_signalForControlEvents:(UIControlEvents)controlEvents;@endNS_ASSUME_NONNULL_END

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

只有一個(gè)方法, 這個(gè)之前講過(guò)是做UIControllerEvent處理的, 再給個(gè)例子:

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

    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(@"點(diǎn)擊了按鈕");
            x.backgroundColor = [UIColor redColor];
        }];
    
    [self.view addSubview:button];

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

 

UIDatePicker+RACSignalSupport.h

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

#import <UIKit/UIKit.h>@class RACChannelTerminal<ValueType>;

NS_ASSUME_NONNULL_BEGIN@interface UIDatePicker (RACSignalSupport)- (RACChannelTerminal<NSDate *> *)rac_newDateChannelWithNilValue:(nullable NSDate *)nilValue;@endNS_ASSUME_NONNULL_END

萬(wàn)碼學(xué)堂,電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),Java培訓(xùn),JavaEE開(kāi)發(fā)培訓(xùn),青島軟件培訓(xùn),軟件工程師培訓(xùn)

它只有一個(gè)綁定的方法, 直接給大家一個(gè)例子:

大概效果為我們?cè)贑ontroller中添加一個(gè)UITextField跟一個(gè)UIDatePicker, 然后獲取他們的RACChannelTerminal,

http://www.cnblogs.com/zhouxihi/p/7226917.html