[iOS development] Summary of the use of ReactiveObjC (RAC)


quote

RAC refers to RactiveCocoa, an open source framework on Github, which can help us provide a lot of convenient event handling solutions, allowing us to handle events more simply and rudely. Now it is divided into ReactiveObjC and ReactiveSwift. The functions of the two frameworks are similar. It is written in OC, so record the usage of ReactiveObjC.


pod 'ReactiveObjC', '~> 3.0.0'

https://github.com/ReactiveCocoa/ReactiveObjC

1. RACSignal signal
/* create signal */
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {

    /* send signal */
    [subscriber sendNext:@"send signal"];

    return nil;
}];

/* Subscribe to signals */
RACDisposable *disposable = [signal subscribeNext:^(id  _Nullable x) {

    NSLog(@"Signal content: %@", x);
}];

/* unsubscribe*/
[disposable dispose];


2. The RACSubject

signal is similar to the usage of the proxy and is usually used to replace the proxy. With it, it is unnecessary to define the proxy.
/* create signal */
RACSubject *subject = [RACSubject subject];

/* send signal */
[subject sendNext:@"send signal"];

/* Subscribe to signals (usually subscribed in other view controllers, similar to the usage of delegates) */
[subject subscribeNext:^(id  _Nullable x) {

    NSLog(@"Signal content: %@", x);
}];


3. RACTuple ancestor

The ancestor of RAC is actually the same as our OC array. It is actually an array that encapsulates our OC.
/* create tuple */
RACTuple *tuple = [RACTuple tupleWithObjects:@"1", @"2", @"3", @"4", @"5", nil];

/* Get content from another array */
RACTuple *tuple = [RACTuple tupleWithObjectsFromArray:@[@"1", @"2", @"3", @"4", @"5"]];

/* Use RAC macros to quickly encapsulate */
RACTuple *tuple = RACTuplePack(@"1", @"2", @"3", @"4", @"5");

NSLog(@"Get the content of the ancestor: %@", tuple[0]);
NSLog(@"The first element: %@", [tuple first]);
NSLog(@"The last element: %@", [tuple last]);


4. Convenience of Array arrays and Dictionary dictionaries

You can omit the use of for loops to traverse.
/* loop through the array */
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
[array.rac_sequence.signal subscribeNext:^(id  _Nullable x) {

    NSLog(@"Array content: %@", x); // x can be any object
}];

/* iterate over the dictionary */
NSDictionary *dictionary = @{@"key1":@"value1", @"key2":@"value2", @"key3":@"value3"};
[dictionary.rac_sequence.signal subscribeNext:^(RACTuple * _Nullable x) {

    RACTupleUnpack(NSString *key, NSString *value) = x; // x is a tuple, this macro can unpack key and value
    NSLog(@"dictionary content: %@:%@", key, value);
}];


The following two methods are to replace all the contents of the array with 0. The first one is a single operation, and the second one is to replace all at once. Neither method will change the contents of the original array, and a new one will be generated after the operation. Arrays, eliminating the need to create a mutable array and then traverse out the individual additions.
/* Content manipulation */
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
NSArray *newArray = [[array.rac_sequence map:^id _Nullable(id  _Nullable value) {

    NSLog(@"Array content: %@", value);

    return @"0"; // replace everything with 0

}] array];

/* 内容快速替换 */
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
NSArray *newArray = [[array.rac_sequence mapReplace:@"0"] array]; // 将所有内容替换为 0

5. 监听 TextField 的输入改变

可以省去设置 delegate 和实现代理方法的步骤。
/* 监听 TextField 的输入(内容改变就会调用) */
[[textField rac_textSignal] subscribeNext:^(NSString * _Nullable x) {
    NSLog(@"输入框内容:%@", x);
}];

/* 添加监听条件 */
[[textField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
    return value.length > 5; // 表示输入文字长度 > 5 时才会调用下面的 block
}] subscribeNext:^(NSString * _Nullable x) {
     NSLog(@"输入框内容:%@", x);
}];

6. 监听 Button 点击事件

可以省去 addTarget 添加事件和创建方法的步骤。
[[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
    NSLog(@"%@ 按钮被点击了", x); // x 是 button 按钮对象
}];

7. 登录按钮状态实时监听

下面表示只有 用户名 和 密码 输入框内容都大于 0 时,登录 按钮才可以点击,而且状态是实时监听的,一句代码就能完成这个功能。
RAC(_loginButton, enabled) = [RACSignal combineLatest:@[_username.rac_textSignal, _password.rac_textSignal] reduce:^id _Nullable(NSString * username, NSString * password){
    return @(username.length && password.length);
}];

8. 监听 Notification 通知事件

可省去在 -(void)dealloc {} 中清除通知和监听通知创建方法的步骤。
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
    NSLog(@"%@ 键盘弹起", x); // x 是通知对象
}];

9. 代替 Delegate 代理方法

可以省去监听以及设置 delegate 的步骤,下面表示只要 view 中执行了 btnClick 这个方法,就会发送信号执行这个回调。
[[view rac_signalForSelector:@selector(btnClick)] subscribeNext:^(RACTuple * _Nullable x) {
    NSLog(@" view 中的按钮被点击了");
}];

10. 代替 KVO 监听

可以代替 KVO 监听,下面表示把监听 view 的 frame 属性改变转换成信号,只要值改变就会发送信号。
[[view rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id  _Nullable x) {
    NSLog(@"属性的改变:%@", x); // x 是监听属性的改变结果
}];

还有一种更简单的写法,就是利用 RAC 的宏,和上面的效果是一样的。
[RACObserve(view, frame) subscribeNext:^(id  _Nullable x) {
    NSLog(@"属性的改变:%@", x); // x 是监听属性的改变结果
}];

11. 代替 NSTimer 计时器

可以代替 NSTimer 使用。
@interface ViewController ()

@property (nonatomic, strong) RACDisposable *disposable;

@end

/* 定义计时器监听 */
self.disposable = [[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {

    NSLog(@"当前时间:%@", x); // x 是当前的系统时间

    /* 关闭计时器 */
    [_disposable dispose];
}];


持续更新,学习到新的知识在记录下来,有需要的可以收藏一下。
将来的你,一定会感激现在拼命的自己,愿自己与读者的开发之路无限美好。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326224694&siteId=291194637