记录一下RAC的使用
阅读原文时间:2023年07月11日阅读:2

1  常规的对数组的操作,包括遍历、刷选、映射、替换

// 遍历
NSArray * array = @[@"",@"",@"",@"",@"",@""];
[array.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"数组内容:%@", x);
}];

注释:可遍历所有元素,但因为内部实现是异步执行的(for in是在当前线程),所以使用时候需要注意时间顺序。

// 刷选
NSArray *filter = [[array.rac_sequence filter:^BOOL(id value) {
return [value integerValue] > ;
}] array];
NSLog(@"filter:%@",filter); // (3,4,5,6)

// 映射
NSArray *map = [[array.rac_sequence map:^id(id value) {
NSInteger a = [value integerValue] * [value integerValue];
return [NSString stringWithFormat:@"%ld", a];
}] array];
NSLog(@"map:%@",map); //(1,4,9,16,25,36)

// 数组替换所有元素

NSArray * array1 = @[@"1",@"2",@"3",@"4",@"5",@"6"];

NSArray * newArray = [[array1.rac_sequence mapReplace:@"99"] array];

NSLog(@"%@",newArray);

2 节流  throttle

表示 指定时间间隔内,不再发送信号  这里添加 throttle, 表示在 1 秒内 text 没有改变时,才会进行搜索请求

UITextField *textfield;
[[[textfield rac_textSignal]
throttle:]
subscribeNext:^(id x) {
NSLog(@"开始搜索请求==%@", x);
}];

3  事件处理    KVO监听   通知等

UITextField * textF;
//实时监听输入框中文字的变化
[[textF rac_textSignal] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"输入框的内容--%@",x);
}];

//UITextField的UIControlEventEditingChanged事件,免去了KVO  
\[\[textF rac\_signalForControlEvents:UIControlEventEditingChanged\] subscribeNext:^(\_\_kindof UIControl \* \_Nullable x) {  
    NSLog(@"%@",x);  
}\];  
//添加监听条件  
\[\[textF.rac\_textSignal filter:^BOOL(NSString \* \_Nullable value) {  
    return \[value isEqualToString:@""\];//此处为判断条件,当输入的字符为100的时候执行下面方法  
}\]subscribeNext:^(NSString \* \_Nullable x) {  
    NSLog(@"输入框的内容为%@",x);  
}\];

UIButton \*loginBtn;  
//监听点击事件  
\[\[loginBtn rac\_signalForControlEvents:UIControlEventTouchUpInside\] subscribeNext:^(\_\_kindof UIControl \* \_Nullable x) {  
    NSLog(@"%@",x);//x为一个button对象,别看类型为UIControl,继承关系UIButton-->UIControl-->UIView-->UIResponder-->NSObject  
    x.frame = CGRectMake(, , , );  
}\];  
//KVO监听按钮frame的改变  
\[\[loginBtn rac\_valuesAndChangesForKeyPath:@"frame" options:(NSKeyValueObservingOptionNew) observer:self\] subscribeNext:^(RACTwoTuple<id,NSDictionary \*> \* \_Nullable x) {  
    NSLog(@"frame改变了%@",x);  
}\];

//定时器  
\[\[RACSignal interval:2.0 onScheduler:\[RACScheduler mainThreadScheduler\]\] subscribeNext:^(NSDate \* \_Nullable x) {  
    NSLog(@"你好哇。");  
    //这里面的方法2秒一循环  
}\];

//通知。。。不需要注销了  
\[\[\[NSNotificationCenter defaultCenter\] rac\_addObserverForName:UIKeyboardDidShowNotification object:nil\] subscribeNext:^(NSNotification \* \_Nullable x) {  
    NSLog(@"%@ 键盘弹起", x); // x 是通知对象  
}\];

4 反向传值,也可以使用block  代理  通知,但是使用RAC最简单

在controller中

SubView *subView = [[SubView alloc] initWithFrame:CGRectMake(, , , )];
subView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:subView];

\[\[subView rac\_signalForSelector:@selector(sendValues:data:)\] subscribeNext:^(RACTuple \* \_Nullable x) {  
    NSLog(@"===111%@",x);  
}\];

在SubView.h中声明这个方法

- (void)sendValues:(NSString *)type data:(NSDictionary *)dicc;

在SubView.m中调用这个方法

- (void)btnAction:(UIButton *)sender
{
[self sendValues:@"" data:@{@"key" : @"values"}];
}

5  RACSubject使用

// 创建信号
RACSubject *subject = [[RACSubject alloc] init];

// 订阅信号  
\[subject subscribeNext:^(id  \_Nullable x) {  
    NSLog(@"==%@",x);  
}\];  
// 发送信号  
\[subject sendNext:@"今天天气还是一如既往的好,希望明天也是如此"\];

6  关于多请求的处理,其实可以使用GCD等方式,但是这里使用RAC还是比较方便的

- (void)demo7
{
RACSignal *single1 = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
// 1:请求数据
// 2:发送数据
[subscriber sendNext:@"single1"];
return nil;
}];

RACSignal \*single2 = \[RACSignal createSignal:^RACDisposable \* \_Nullable(id<RACSubscriber>  \_Nonnull subscriber) {  
    // 1:请求数据  
    // 2:发送数据  
    \[subscriber sendNext:@"single2"\];  
    return nil;  
}\];

// 订阅信号  
\[single1 subscribeNext:^(id  \_Nullable x) {  
    NSLog(@"------处理1..%@",x);  
}\];

\[single2 subscribeNext:^(id  \_Nullable x) {  
    NSLog(@"------处理2。。%@",x);  
}\];

// 当数组中所有信号都发送了数据,才会执行selector,必须带参,参数是sendNext发送过来的,必须和信号一一对应  
// 参数:每个信号发送的数据,这里必须要带参数,不然会崩溃  
\[self rac\_liftSelector:@selector(updateUIOneData:TwoData:) withSignalsFromArray:@\[single1,single2\]\];  

}

  • (void)updateUIOneData:(id)x1 TwoData:(id)x2
    {
    NSLog(@"更新UI:%@----%@",x1,x2);
    }

7. 使用宏

UILabel *myLabel;
// 监测某个对象的属性,发生变化时回直接回调给block
[RACObserve(myLabel, text) subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];

// RAC:把一个对象的某个属性绑定一个信号,只要发出信号,就会把信号的内容给对象的属性赋值  
// 给label的text属性绑定了文本框改变的信号  
UITextField \*textfield;  
RAC(myLabel, text) = textfield.rac\_textSignal;  
\[textfield.rac\_textSignal subscribeNext:^(id x) {  
    myLabel.text = x;  
}\];

举一个监听的例子。

需求就是监听scrollerview 的滑动。当滑动的时候就输出日志。如下:

UIScrollView *scrolView = [[UIScrollView alloc] initWithFrame:CGRectMake(, , , )];
scrolView.contentSize = CGSizeMake(, );
scrolView.backgroundColor = [UIColor greenColor];
[self.view addSubview:scrolView];
[RACObserve(scrolView, contentOffset) subscribeNext:^(id x) {
NSLog(@"success");
}];

8. 补一下merge 和 combineLatest 的用法。

先看代码吧:

RACSubject *aaaaa = [RACSubject subject];
RACSubject *bbbbb = [RACSubject subject];
[[RACSignal merge:@[aaaaa,bbbbb]]subscribeNext:^(id x) {
NSLog(@"信号发送combineLatest:%@",x);
}];

\[aaaaa sendNext:@""\];  
\[bbbbb sendNext:@""\];

RACSubject *aaaaa = [RACSubject subject];
RACSubject *bbbbb = [RACSubject subject];
[[RACSignal combineLatest:@[aaaaa,bbbbb]]subscribeNext:^(id x) {
NSLog(@"信号发送combineLatest:%@",x);
}];

\[aaaaa sendNext:@""\];  
\[bbbbb sendNext:@""\];

这两个非常相似,merge指的是只要发送一个信号,block就会回掉,然后回调回来的是那个改变你的singal的值

而combineLatest也是只要发送一个信号,block就会回调,然后把所有信号的值以元祖的形式返回来

参考文章: https://www.jianshu.com/p/666bc733559a