一、Reactive 之 ObjC 介紹
RAC - 響應式編程,幫我們簡單粗暴地處理事件
RAC 是通過信號 處理事件的
RAC能滿足我們一個需求,就是所有需求
創(chuàng)建信號 - 訂閱信號 - 發(fā)送信號

// 創(chuàng)建信號必須先訂閱
// 訂閱信號必須先發(fā)送
// 創(chuàng)建信號(冷信號)
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 發(fā)送信號
[subscriber sendNext:@"This is RAC"];
return nil;
}];
// 訂閱信號(熱信號)
[signal subscribeNext:^(id _Nullable x) {
// x : 指的是信號本身的數(shù)據(jù)內(nèi)容
NSLog(@"x = %@", x);
}];
取消訂閱
// 1.信號發(fā)送完成
// 2.信號發(fā)送失敗
// 訂閱的取消取決于 `subscriber` 是否存在
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"this is RAC"];
self.subscriber = subscriber;
return [RACDisposable disposableWithBlock:^{
NSLog(@"我取消了訂閱");
}];
}];
RACDisposable *disposable = [signal subscribeNext:^(id _Nullable x) {
NSLog(@"disposable - %@", x);
}];
[disposable dispose];
二、初步使用(demo)
-
KVO
// KVO
self.person = [[Person alloc] init];
// 監(jiān)聽 person 的 name 屬性
[_RACObserve(self.person, name) subscribeNext:^(id _Nullable x) {
NSLog(@"name - %@", x);
}];
```
* ######action target
// target
[[self.RACAcion rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"Click - RACAcion");
}];
* ######通知
// 通知, 監(jiān)聽鍵盤彈出通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidChangeFrameNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"motification - %@", x);
}];
```
-
文本框代理
// 充當textView的代理
[[self.RACTextView rac_textSignal] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"textView - %@", x);
}];
-
touchesBegin 輔助
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// KVO
// 在這里改變name的值
self.person.name = [NSString stringWithFormat:@"ThinkDifferent%u", arc4random_uniform(10000)];
// 通知 - 退下鍵盤
[self.view endEditing:true];
}
三、進階使用
界面有多個網(wǎng)絡請求, 當所有網(wǎng)絡請求都完成時, 才能展示界面.
- (void)viewDidLoad {
[super viewDidLoad];
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// requestA()
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:3.0];
[subscriber sendNext:@"網(wǎng)絡A加載完成"];
});
return [RACDisposable disposableWithBlock:^{
NSLog(@"取消A信號");
}];
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// requestB()
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:5.0];
[subscriber sendNext:@"網(wǎng)絡B加載完成"];
});
return [RACDisposable disposableWithBlock:^{
NSLog(@"取消B信號");
}];
}];
[self rac_liftSelector:@selector(responseA:B:) withSignalsFromArray:@[signalA, signalB]];
}
- (void)responseA:(id)a B:(id)b {
NSLog(@"%@, %@", a, b);
}
當一個界面有多個UITextField和UIButton選項,只有所有的UITextField都有值時UIButton才能可以點擊。
- (void)viewDidLoad {
[super viewDidLoad];
[self rac_liftSelector:@selector(responseA:B:) withSignalsFromArray:@[self.textField1.rac_textSignal, self.textField2.rac_textSignal]];
}
- (void)responseA:(NSString *)str1 B:(NSString *)str2 {
if(![str1 isEqualToString:@""] && ![str2 isEqualToString:@""]) {
self.btn.enabled = YES;
} else {
self.btn.enabled = NO;
}
}
四、應用
發(fā)送短信驗證碼Demo - textView拖動不會影響Timer