RAC简介
一. 什么是ReactiveCocoa?
ReactiveCocoa(其简称为RAC)是由Github 开源的一个应用于iOS和OS X开发的新框架。RAC具有函数式编程(FP)和响应式编程(RP)的特性。它主要吸取了.Net的 Reactive Extensions的设计和实现。
ReactiveCocoa 的宗旨是Streams of values over time ,随着时间变化而不断流动的数据流。
ReactiveCocoa 主要解决了以下这些问题:
-
UI数据绑定
- UI控件通常需要绑定一个事件,RAC可以很方便的绑定任何数据流到控件上。
-
用户交互事件绑定
- RAC为可交互的UI控件提供了一系列能发送Signal信号的方法。这些数据流会在用户交互中相互传递。
-
解决状态以及状态之间依赖过多的问题
- 有了RAC的绑定之后,可以不用在关心各种复杂的状态,isSelect,isFinish……也解决了这些状态在后期很难维护的问题。
-
消息传递机制的大统一
- OC中编程原来消息传递机制有以下几种:Delegate,Block Callback,Target-Action,Timers,KVO,objc上有一篇关于OC中这5种消息传递方式改如何选择的文章Communication Patterns,推荐大家阅读。现在有了RAC之后,以上这5种方式都可以统一用RAC来处理。 其实也就是一下的这些消息传递机制。RAC都用了统一的方式封装起来让我们更加方便的去使用。
RAC的常用方法
1.通知NSNotificationCenter
- 普通写法
- 添加键盘弹出的通知addObserver
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; 复制代码
- 实现方法
- (void) keyboardWillShow:(NSNotification *)note { NSLog(@"键盘弹出了"); } 复制代码
- 移除通知
- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; } 复制代码
- RAC 写法
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) { NSLog(@"%@",x); }]; 复制代码
- x的打印结果
NSConcreteNotification 0x6000000c5170 {name = UIKeyboardWillShowNotification; userInfo = { UIKeyboardAnimationCurveUserInfoKey = 7; UIKeyboardAnimationDurationUserInfoKey = "0.25"; UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {390, 336}}"; UIKeyboardCenterBeginUserInfoKey = "NSPoint: {195, 1012}"; UIKeyboardCenterEndUserInfoKey = "NSPoint: {195, 676}"; UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 844}, {390, 336}}"; UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 508}, {390, 336}}"; UIKeyboardIsLocalUserInfoKey = 1; }} 复制代码
2.KVO
-
普通写法
- 模型
@interface TestModel : NSObject @property (assign, nonatomic) int age; @property (assign, nonatomic) int height; @end 复制代码
#import "KVOViewController.h" #import "TestModel.h" @interface KVOViewController () @property (strong, nonatomic) TestModel *testModel1; @end @implementation KVOViewController - (void)viewDidLoad { [super viewDidLoad]; self.testModel1 = [[TestModel alloc] init]; self.testModel1.age = 1; self.testModel1.height = 11; // 给testModel1对象添加KVO监听 当KVO监听age属性变化 NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld; [self.testModel1 addObserver:self forKeyPath:@"age" options:options context:@"123"]; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { self.testModel1.age = 20; self.testModel1.height = 30; } // 当监听对象的属性值发生改变时,就会调用 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { NSLog(@"监听到%@的%@属性值改变了 - %@ - %@", object, keyPath, change, context); } - (void)dealloc { [self.testModel1 removeObserver:self forKeyPath:@"age"]; [self.testModel1 removeObserver:self forKeyPath:@"height"]; } 复制代码
- RAC写法
#define RACObserve(TARGET, KEYPATH) _RACObserve(TARGET, KEYPATH)
[RACObserve(self.testModel1, age)subscribeNext:^(id _Nullable x) { NSLog(@"%@",x); }]; 复制代码
3.代理 Delegate
- 普通写法
1. 遵守代理 <UITextFieldDelegate>
2. 空间 @property (weak, nonatomic) IBOutlet UITextField *textField;
3. 代理的响应者 self.textField.delegate = self;
4.代理方法
- (void)textFieldDidBeginEditing:(UITextField *)textField {
NSLog(@"开始编辑");
}
复制代码
- RAC写法
self.textField.delegate = self;
[[self rac_signalForSelector:@selector(textFieldDidBeginEditing:) fromProtocol:@protocol(UITextFieldDelegate)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"%@",x);
}];
<RACTuple: 0x600000dd9130> (
"<UITextField: 0x127d0bf90; frame = (97 118; 220 34); text = ''; opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x6000001e6f70>; borderStyle = RoundedRect; background = <_UITextFieldSystemBackgroundProvider: 0x600000f8eb80: backgroundView=<_UITextFieldRoundedRectBackgroundViewNeue: 0x127d0e710; frame = (0 0; 220 34); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x600000f8ec60>>, fillColor=<UIDynamicModifiedColor: 0x6000001874e0; contrast = normal, baseColor = <UIDynamicSystemColor: 0x600001a9bb40; name = systemRedColor>>, textfield=<UITextField 0x127d0bf90>>; layer = <CALayer: 0x600000fe3ee0>>"
)
复制代码
4.Target-Action
- 普通写法
[self.button addTarget:self action:@selector(Click:) forControlEvents:UIControlEventTouchUpInside];
- (void)Click:(UIButton *)sender {
NSLog(@"按钮被点击");
}
复制代码
- RAC
[[self.button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"%@",x);
}];
<UIButton: 0x15a50d9f0; frame = (101 240; 213 205); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x60000262fb60>>
复制代码
5.UITextField
- RAC 写法:
[self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
NSLog(@"%@",x);
}];
复制代码
当在self.textField输入文字h时,会实时打印出变化后的文字
2019-05-16 18:02:58.562309+0800 001---RAC[54530:4536864] h
2019-05-16 18:02:59.049225+0800 001---RAC[54530:4536864] hh
2019-05-16 18:02:59.288995+0800 001---RAC[54530:4536864] hhh
复制代码
6.手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
self.label.userInteractionEnabled = YES;
[self.label addGestureRecognizer:tap];
[tap.rac_gestureSignal subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
NSLog(@"%@",x);
}];
复制代码
7、数组和字典的遍历
- 数组
TestModel *model1 = [[TestModel alloc] init];
model1.age = 1;
model1.height = 11;
TestModel *model2 = [[TestModel alloc] init];
model2.age = 2;
model2.height = 22;
TestModel *model3 = [[TestModel alloc] init];
model3.age = 3;
model3.height = 33;
NSArray *array = @[model1,model2,model3];
[array.rac_sequence.signal subscribeNext:^(TestModel * _Nullable x) {
NSLog(@"%d",x.age);
}];
复制代码
- 字典
NSDictionary *dict = @{@"name":@"凡几多",@"age":@"20",@"sex":@"男"};
[dict.rac_sequence.signal subscribeNext:^(id _Nullable x) {
//元祖
NSLog(@"%@",x);
RACTwoTuple *tuple = (RACTwoTuple *)x;
NSLog(@"key == %@ , value = %@",tuple[0],tuple[1]);
}];
复制代码
8、计时器
- NSTimer
NSTimer *timer = [NSTimer timerWithTimeInterval:30.0 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES]; // 需要加入手动RunLoop,需要注意的是在NSTimer工作期间self是被强引用的
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; // 使用NSRunLoopCommonModes才能保证RunLoop切换模式时,NSTimer能正常工作。
停止计时器
- (void)stopTimer {
if (_timer) {
[_timer invalidate];
}
}
复制代码
- RAC
- 主线程
[[RACSignal interval:2.0 onScheduler:[RACScheduler mainThreadScheduler]]subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"%@",x);
NSLog(@"%@",[NSThread currentThread]);
}];
- 子线程
[[RACSignal interval:2.0 onScheduler:[RACScheduler schedulerWithPriority:RACSchedulerPriorityHigh name:@"abc"]] subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"%@",[NSThread currentThread]);
}];
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END