ReactiveCocoa(其简称为RAC)是由Github 开源的一个应用于iOS和OS X开发的新框架。RAC具备函数式编程(FP)和响应式编程(RP)的特性。它主要吸收了.Net的 Reactive Extensions的设计和实现。编程
ReactiveCocoa 的宗旨是Streams of values over time ,随着时间变化而不断流动的数据流。数组
ReactiveCocoa 主要解决了如下这些问题:markdown
UI数据绑定框架
用户交互事件绑定async
解决状态以及状态之间依赖过多的问题ide
消息传递机制的大统一函数式编程
[[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];
}
复制代码
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"%@",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;
}}
复制代码
普通写法函数
@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"];
}
复制代码
#define RACObserve(TARGET, KEYPATH) _RACObserve(TARGET, KEYPATH)oop
[RACObserve(self.testModel1, age)subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
复制代码
1. 遵照代理 <UITextFieldDelegate>
2. 空间 @property (weak, nonatomic) IBOutlet UITextField *textField;
3. 代理的响应者 self.textField.delegate = self;
4.代理方法
- (void)textFieldDidBeginEditing:(UITextField *)textField {
NSLog(@"开始编辑");
}
复制代码
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>>"
)
复制代码
[self.button addTarget:self action:@selector(Click:) forControlEvents:UIControlEventTouchUpInside];
- (void)Click:(UIButton *)sender {
NSLog(@"按钮被点击");
}
复制代码
[[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>>
复制代码
[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
复制代码
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
self.label.userInteractionEnabled = YES;
[self.label addGestureRecognizer:tap];
[tap.rac_gestureSignal subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
NSLog(@"%@",x);
}];
复制代码
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]);
}];
复制代码
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];
}
}
复制代码
- 主线程
[[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]);
}];
复制代码
参考文章 利用栅栏函数完成任务的调度post
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
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];
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrent", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"🔞 START: %@", [NSThread currentThread]);
dispatch_async(concurrentQueue, ^{
[array.rac_sequence.signal subscribeNext:^(TestModel * _Nullable x) {
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"%d",x.age);
}];
}); // ⬅️ 任务一
dispatch_barrier_async(concurrentQueue, ^{ sleep(3); NSLog(@"🚥🚥 %@", [NSThread currentThread]);}); // ⬅️ Barrie 任务
dispatch_async(concurrentQueue, ^{ NSLog(@"111");}); // ⬅️ 任务四
NSLog(@"🔞 END: %@", [NSThread currentThread]);
}
复制代码