本demo詳見github
1.常見的用法
myRedView.h
#import <UIKit/UIKit.h>
@interface myRedView : UIView
@end
myRedView.m
#import "myRedView.h"
@implementation myRedView
-(instancetype)initWithFrame:(CGRect)frame{
if([super initWithFrame:frame]){
self.backgroundColor = [UIColor redColor];
UIButton *btn = [UIButton new];
btn.frame = CGRectMake(0, 0, 40, 40);
[btn setBackgroundColor:[UIColor greenColor]];
[self addSubview:btn];
[btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
-(void)btnClick{
NSLog(@"點擊了紅色view中的按鈕");
// 通知控制器做事情
}
@end
RACCommonUsages.h
#import <UIKit/UIKit.h>
@interface RACCommonUsages : UIViewController
@end
RACCommonUsages.m
#import "RACCommonUsages.h"
#import "myRedView.h"
#import <ReactiveObjC.h>
@interface RACCommonUsages ()
@property (nonatomic,assign)int age;
@end
@implementation RACCommonUsages
- (void)viewDidLoad {
[super viewDidLoad];
self.age = 0;
[self RAC_Delegate];
[self RAC_KVO];
[self RAC_ObserveAction];
[self RAC_ObserveTextFieldAndNotification];
[self ARC_MoreSituations];
}
//控制器要監(jiān)聽紅色的view上的button的點擊
-(void)RAC_Delegate{
// 1.RAC替換代理
// RAC:判斷下一個方法有沒有調(diào)用,如果調(diào)用了就會自動發(fā)送一個信號給你
// 只要self調(diào)用viewDidLoad就會轉(zhuǎn)換成一個信號
// 監(jiān)聽_redView有沒有調(diào)用btnClick,如果調(diào)用了就會轉(zhuǎn)換成信號
myRedView *v = [[myRedView alloc]initWithFrame:CGRectMake(0, 100, 100, 200)];
[self.view addSubview:v];
[[v rac_signalForSelector:@selector(btnClick)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"控制器知道,點擊了紅色的view");
}];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.age++;
NSLog(@"點擊增的值:%d",self.age);
}
-(void)RAC_KVO{
// 2.KVO
// 監(jiān)聽哪個對象的屬性改變
// 方法調(diào)用者:就是被監(jiān)聽的對象
// KeyPath:監(jiān)聽的屬性
// 把監(jiān)聽到內(nèi)容轉(zhuǎn)換成信號
[[self rac_valuesForKeyPath:@"age" observer:self] subscribeNext:^(id _Nullable x) {
NSLog(@"監(jiān)聽的值%@",x);
}];
}
-(void)RAC_ObserveAction{
UIButton *btn = [UIButton new];
btn.frame = CGRectMake(20, 400, 40, 40);
[btn setBackgroundColor:[UIColor lightGrayColor]];
[self.view addSubview:btn];
//3.監(jiān)聽事件
//只要產(chǎn)生UIControlEventTouchUpInside就會轉(zhuǎn)換成信號
[[btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"點擊了btn");
}];
}
-(void)RAC_ObserveTextFieldAndNotification{
UITextField *textF = [[UITextField alloc]init];
textF.borderStyle = UITextBorderStyleRoundedRect;
textF.frame = CGRectMake(200, 100, 100, 40);
[self.view addSubview:textF];
//4.監(jiān)聽通知
// 只要發(fā)出這個通知,又會轉(zhuǎn)換成一個信號
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
NSLog(@"彈出鍵盤");
}];
//5.監(jiān)聽文本框文字改變
// 獲取文本框文字改變的信號
[textF.rac_textSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
}
//6.兩種(多種)情況都有數(shù)據(jù)的時候才去做相應(yīng)的事情
-(void)ARC_MoreSituations{
// 創(chuàng)建熱門商品的信號
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 處理信號
NSLog(@"請求熱門商品");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 發(fā)送數(shù)據(jù)
[subscriber sendNext:@"熱門商品"];
});
return nil;
}];
// 創(chuàng)建熱門商品的信號
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 處理信號
NSLog(@"請求最新商品");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 發(fā)送數(shù)據(jù)
[subscriber sendNext:@"最新商品"];
});
return nil;
}];
// RAC:就可以判斷兩個信號有沒有都發(fā)出內(nèi)容
// SignalsFromArray:監(jiān)聽哪些信號的發(fā)出
// 當(dāng)signals數(shù)組中的所有信號都發(fā)送sendNext就會觸發(fā)方法調(diào)用者(self)的selector
// 注意:selector方法的參數(shù)不能亂寫,有幾個信號就對應(yīng)幾個參數(shù)
// 不需要主動訂閱signalA,signalB,方法內(nèi)部會自動訂閱
[self rac_liftSelector:@selector(updateUIWithHot:new:) withSignalsFromArray:@[signalA,signalB]];
}
// 更新UI
- (void)updateUIWithHot:(NSString *)hot new:(NSString *)new
{
NSLog(@"更新UI");
}
-(void)dealloc{
NSLog(@"%s",__FUNCTION__);
}
@end
2.RAC常見的宏
#import "RACCommonDefines.h"
#import <ReactiveObjC.h>
@interface RACCommonDefines ()
@property (nonatomic,strong)UITextField *textF;
@property (nonatomic,strong)UILabel *showLab;
@end
@implementation RACCommonDefines
- (void)viewDidLoad {
[super viewDidLoad];
self.textF = [[UITextField alloc]initWithFrame:CGRectMake(20, 100, 300, 40)];
self.textF.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:self.textF];
self.showLab = [[UILabel alloc]initWithFrame:CGRectMake(20, 200, 300, 40)];
[self.view addSubview:self.showLab];
self.showLab.backgroundColor = [UIColor redColor];
[self RAC_define];
[self RAC_KVO];
[self RAC_RACTuple];
}
//RAC宏
-(void)RAC_define{
RAC(self.showLab, text) = self.textF.rac_textSignal;
/*
[self.textF.rac_textSignal subscribeNext:^(id x) {
self.showLab.text = x;
}];
*/
}
-(void)RAC_KVO{
[RACObserve(self.showLab, text) subscribeNext:^(id x) {
NSLog(@"KVO監(jiān)聽文本的變化%@", x);
}];
}
-(void)CyclicReferences{
/*
@weakify(self);
@strongify(self);
*/
}
/*
* 元祖
* 快速包裝一個元組
* 把包裝的類型放在宏的參數(shù)里面,就會自動包裝
*/
-(void)RAC_RACTuple{
RACTuple *tuple = RACTuplePack(@1,@2,@4);
// 宏的參數(shù)類型要和元祖中元素類型一致战授, 右邊為要解析的元祖享甸。
RACTupleUnpack_(NSNumber *num1, NSNumber *num2, NSNumber * num3) = tuple;// 4.元祖
// 快速包裝一個元組
// 把包裝的類型放在宏的參數(shù)里面,就會自動包裝
NSLog(@"%@ %@ %@", num1, num2, num3);
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];
}
-(void)dealloc{
NSLog(@"%s",__FUNCTION__);
}
@end
3.發(fā)送驗證碼
#import "Demo.h"
#import <ReactiveObjC.h>
@interface Demo ()
@property (nonatomic,assign)int time;
@property (nonatomic,strong) RACDisposable *disposable;
@end
@implementation Demo
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(20, 100, 100, 60)];
[btn setBackgroundColor:[UIColor redColor]];
[btn setTitle:@"發(fā)送驗證碼" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(reSendCode:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
-(void)reSendCode:(UIButton*)sender{
self.time = 15;
@weakify(self);
self.disposable = [[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {
@strongify(self);
self.time--;
NSString *btnText = self.time >0 ? [NSString stringWithFormat:@"%ds",self.time]:@"發(fā)送驗證碼";
[sender setTitle:btnText forState:(UIControlStateNormal)];
if(self.time>0){
sender.enabled = NO;
}else{
sender.enabled = YES;
[self.disposable dispose];//在我們?nèi)∠嗛喌哪且粍x那,幫我們打斷了循環(huán)引用
}
}];
}
-(void)dealloc{
NSLog(@"%s",__FUNCTION__);
}
@end
友情鏈接: