@interface ViewController () @property (weak, nonatomic) IBOutlet lwRedView *redView; @property (weak, nonatomic) IBOutlet UIButton *lwbtn; @property (weak, nonatomic) IBOutlet UITextField *phoneTF; @property (weak, nonatomic) IBOutlet UITextField *pwTF; @property (weak, nonatomic) IBOutlet UIButton *loginBtn; @property (nonatomic, strong) RACCommand * loginCommand; @end @implementation ViewController - (void)tryUseRACMethod { // map 能夠轉換 信號 (文本輸入的字符串 轉化爲 是否長度爲3的bool值) // 驗證輸入框的合法性 RACSignal *phoneValidSignal = [self.phoneTF.rac_textSignal map:^id _Nullable(NSString * _Nullable value) { return @((value.length == 3)); }]; RACSignal *pwValidSignal = [self.pwTF.rac_textSignal map:^id _Nullable(NSString * _Nullable value) { return @(value.length>1&&value.length <= 6); }]; // 根據監聽輸入框的內容,是否合法,來改變輸入框的背景色 [[phoneValidSignal map:^id _Nullable(id _Nullable value) { return [value boolValue] ? UIColor.clearColor : UIColor.yellowColor; }] subscribeNext:^(id _Nullable x) { self.phoneTF.backgroundColor = x; }]; // RAC(_phoneTF,backgroundColor) = [phoneValidSignal map:^id _Nullable(id _Nullable value) { // return value ? UIColor.clearColor : UIColor.yellowColor; // }]; RAC(_pwTF,backgroundColor) = [pwValidSignal map:^id _Nullable(id _Nullable value) { return [value boolValue] ? UIColor.clearColor : UIColor.yellowColor; }]; // 合併信號(手機號,密碼輸入框),建立一個新的關於按鈕狀態的信號,改變按鈕的狀態 RACSignal *activeBtnSignal = [RACSignal combineLatest:@[phoneValidSignal,pwValidSignal] reduce:^id _Nullable(NSNumber *ph,NSNumber *pw){ return @([ph boolValue] && [pw boolValue]); }]; // 把按鈕 和信號綁定 [activeBtnSignal subscribeNext:^(id _Nullable x) { self.loginBtn.backgroundColor = [x boolValue] ? UIColor.redColor : UIColor.grayColor; }]; /// 建立一個登錄請求的信號 RACSignal *loginSignal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { [self loginRequestWithPhone:self.phoneTF.text pw:self.pwTF.text callBlock:^(BOOL res) { [subscriber sendNext:@(res)]; [subscriber sendCompleted]; }]; return nil; }]; [[[[self.loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] doNext:^(id _Nullable x) { // 邊際效應 不改變信號自己 self.loginBtn.enabled = NO; }] // flattenMap 返回信號內容 flattenMap:^__kindof RACSignal * _Nullable(__kindof UIControl * _Nullable value) { return loginSignal; }] subscribeNext:^(id _Nullable x) { NSLog(@"----------%@",x); self.loginBtn.enabled = YES; }]; [self.loginCommand.executionSignals.switchToLatest subscribeNext:^(id _Nullable x) { NSLog(@"--------logincommand:%@",x); }]; [[self.loginCommand executionSignals] subscribeNext:^(id _Nullable x) { NSLog(@"--------1:%@",x); // 開始網絡請求的信號 self.view.backgroundColor = [UIColor redColor]; [x subscribeNext:^(id _Nullable x) { // 網絡請求的回調信號 NSLog(@"--------2:%@",x); self.view.backgroundColor = [UIColor whiteColor]; }]; }]; [[self.loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) { // 開始執行command [self.loginCommand execute:nil]; }]; } // 模擬網絡請求 - (void)loginRequestWithPhone:(NSString *)phone pw:(NSString *)pw callBlock:(callBlock)callBlock { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if ([phone isEqualToString:@"120"] && [pw isEqualToString:@"123"]) { if(callBlock) callBlock(YES); }else{ if(callBlock) callBlock(NO); } }); } - (RACCommand*)loginCommand { if (!_loginCommand) { _loginCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) { return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { NSString *phone = @"120"; NSString *pw = @"123"; /// 網絡請求 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if ([phone isEqualToString:@"120"] && [pw isEqualToString:@"123"]) { [subscriber sendNext:@(1)]; }else{ [subscriber sendNext:@(0)]; } [subscriber sendCompleted]; }); return nil; }]; }]; } return _loginCommand; } - (void)testRACMethod { /** 監聽方法 */ [[self.redView rac_signalForSelector:@selector(clickBtn:)] subscribeNext:^(RACTuple * _Nullable x) { NSLog(@"========%@",x); }]; /// 事件的響應 [[self.lwbtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) { NSLog(@"------%@",x); }]; /** 監聽 kvo */ [[self.redView rac_valuesForKeyPath:@"frame" observer:nil] subscribeNext:^(id x) { NSLog(@"---------%@",x); }]; // 宏定義的KVO [RACObserve(self.redView, frame) subscribeNext:^(id _Nullable x) { NSLog(@"---------%@",x); }]; /** 監聽 通知 */ [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"rac_noti_key" object:nil] subscribeNext:^(NSNotification * _Nullable x) { NSLog(@"-------------%@",x); }]; // 監聽輸入框 [self.wltf.rac_textSignal subscribeNext:^(NSString * _Nullable x) { NSLog(@"------tf:%@",x); }]; // 爲輸入框添加 filter 過濾器 [[self.wltf.rac_textSignal filter:^BOOL(NSString * _Nullable value) { return value.length < 4; }] subscribeNext:^(NSString * _Nullable x) { NSLog(@"-------filter_text:%@",x); }]; [[[self.wltf.rac_textSignal map:^id _Nullable(NSString * _Nullable value) { // 轉換信號流爲 字符串長度信號流 return @(value.length); }] filter:^BOOL(NSNumber* _Nullable value) { return [value integerValue] > 3; }] subscribeNext:^(id _Nullable x) { NSLog(@"==============%ld",[x integerValue]); }]; /// 手勢的使用 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init]; [tap.rac_gestureSignal subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) { NSLog(@"-------%@",x); }]; [self.view addGestureRecognizer:tap]; } - (void)viewDidLoad { [super viewDidLoad]; [self tryUseRACMethod]; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { _redView.frame = CGRectMake(10, 10, 300, 300); } @end