RAC整理

作者: Xl_Lee | 来源:发表于2021-03-30 14:06 被阅读0次

    RAC常用的方法,搭配@weakify(self); @weakify(self);

      1. 通知
    # RAC中的通知不需要手动remove observer,其内部已经实现
      @weakify(self);
     [[[NSNotificationCenter defaultCenter] rac_addObserverForName:kNotificationName object:nil] 
      subscribeNext:^(NSNotification * _Nullable x) {
            @strongify(self);
    
        }];
    
    
      1. control
    # control的通用方法
     @weakify(self);
     [[button rac_signalForControlEvents:UIControlEventTouchUpOutside] subscribeNext:^(__kindof UIControl * _Nullable  x) {
            @strongify(self);
    
        }];
    
    # 监听textfild的UIControlEventEditingChanged事件
    # 方式一:
    [[textFild rac_signalForControlEvents:UIControlEventEditingChanged] subscribeNext:^(__kindof UIControl * _Nullable  x){
        NSLog(@"change");
    }];
    # 方式二:
    [[self.textFild rac_textSignal] subscribeNext:^(NSString *x) {
        NSLog(@"%@",x);
    }];
    //这样就是每次改变TextFild都输出改变后的结果
    
      1. Gesturer
    # 再比如给我们的某个label添加一个手势动作,我们也可以用简单的RAC代码完成
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
    [[tap rac_gestureSignal] subscribeNext:^(__kindof   UIGestureRecognizer  * _Nullable x) {
        NSLog(@"tap");
    }];
    [self.view addGestureRecognizer:tap];
    
      1. 代理

    用RAC写代理是有局限的,它只能实现返回值为void的代理方法,RAC为我们提供了一个rac_signalForSelector: fromProtoc:方法帮我们实现代理

    # alert方式一:
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"RAC" message:@"RAC TEST" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"other", nil];
    [[self rac_signalForSelector:@selector(alertView:clickedButtonAtIndex:) fromProtocol:@protocol(UIAlertViewDelegate)] subscribeNext:^(RACTuple *tuple) {
     # tuple封装了方法的参数,可以取出参数对应的值
        NSLog(@"%@",tuple.first);
     #可以看出tuple.second是点击Item的Index
        NSLog(@"%@",tuple.second);
        NSLog(@"%@",tuple.third);
    }];
    [alertView show];
    
    #查看RACTuple
    @interface RACTuple : NSObject <NSCoding, NSCopying, NSFastEnumeration>
    
    @property (nonatomic, readonly) NSUInteger count;
    
    /// These properties all return the object at that index or nil if the number of 
    /// objects is less than the index.
    @property (nonatomic, readonly, nullable) id first;
    @property (nonatomic, readonly, nullable) id second;
    @property (nonatomic, readonly, nullable) id third;
    @property (nonatomic, readonly, nullable) id fourth;
    @property (nonatomic, readonly, nullable) id fifth;
    @property (nonatomic, readonly, nullable) id last;
    
    
    2021-03-19 12:24:29.114 RACStudyTest[5003:388870] <UIAlertView: 0x7ff260c90c70; frame = (0 0; 0 0); layer = <CALayer: 0x7ff260c91030>>
    2021-03-19 12:24:29.115 RACStudyTest[5003:388870] 1
    2021-03-19 12:24:29.115 RACStudyTest[5003:388870] (null)
    
    # alert方式二
    [[alertView rac_buttonClickedSignal] subscribeNext:^(id x) {
    #  这里的x是点击Item的Index
        NSLog(@"%@",x);
    }];
    
      1. kvo

    RAC中得KVO大部分都是宏定义,所以代码异常简洁,简单来说就是 RACObserve(TARGET, KEYPATH)这种形式,TARGET是监听目标,KEYPATH是要观察的属性值

    
     @weakify(self);
    [RACObserve(object, propertyChanged) subscribeNext:^(id propertyChangedValue) {
            @strongify(self);    
    
    }];
    
      [[RACSignal combineLatest:@[RACObserve(self.messageViewController, unReadMessageCount),RACObserve(self.friendsVc, unReadMessageCount),RACObserve(self, unReadSystemCount)]] subscribeNext:^(RACTuple *x) {
            @strongify(self);
            NSInteger first = ((NSNumber *)x.first).integerValue;
            NSInteger second = ((NSNumber *)x.second).integerValue;
            NSInteger third = ((NSNumber *)x.third).integerValue;
            JHTabBarController *tabbarVC = (JHTabBarController *)self.tabBarController;
            [tabbarVC.customTabBar hideBadgeOnItemIndex:3];//隐藏未读小红点
            if (first>0||second>0||third>0) {
                [tabbarVC.customTabBar showBadgeOnItemIndex:3 value:(first+second+third)];//显示未读小红点
            }
        }];
    

    RACSignal 封装请求

    - (RACSignal *)sendShareMessageWithModel:(JH_ChatRoomBaseModel *)messageModel {
        
        @weakify(self);
        
        return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            
            @strongify(self);
            
            [self addMessageModelToDatabase:messageModel];
            
            //通过Socket向服务器发送消息
            [self sendMessageToServerWithModel:messageModel];
            // 给订阅者发送消息
            [subscriber sendNext:@(YES)];
            [subscriber sendCompleted];
            
            return nil;
        }];
    }
    

    RAC相关类

    RACSignal的使用

       // 创建一个信号
       RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
           
           NSLog(@"创建一个信号");
           
           // 发送信号
           [subscriber sendNext:@"发送一个信号"];
           
           return nil;
       }];
       
       // 订阅一个信号
       [signal subscribeNext:^(id  _Nullable x) {
           
           NSLog(@"订阅一个信号");
           NSLog(@"订阅到的: %@", x);
       }];
    
    2017-07-22 17:37:09.294 RAC[66282:12633516] 创建一个信号
    2017-07-22 17:37:09.295 RAC[66282:12633516] 订阅一个信号
    2017-07-22 17:37:09.295 RAC[66282:12633516] 订阅到的: 发送一个信号
    

    sendNext就把内容传递到了Next的block中了

    UITextField+RACSignalSupport.h

    #import <UIKit/UIKit.h>
    
    @class RACChannelTerminal<ValueType>;
    @class RACSignal<__covariant ValueType>;
    
    NS_ASSUME_NONNULL_BEGIN
    # 
    @interface UITextField (RACSignalSupport)
    #  
    - (RACSignal<NSString *> *)rac_textSignal;
    # 用于双向绑定
    - (RACChannelTerminal<NSString *> *)rac_newTextChannel;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    rac_textSignal

    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];
        
        textField.center          = self.view.center;
        textField.backgroundColor = [UIColor yellowColor];
        
        [[textField
            rac_textSignal]
            subscribeNext:^(NSString * _Nullable x) {
                
                NSLog(@"%@", x);
            }];
        
        [self.view addSubview:textField];
    
    2017-07-23 22:55:45.686 RAC[70205:14118946] 1
    2017-07-23 22:55:46.139 RAC[70205:14118946] 11
    2017-07-23 22:55:46.798 RAC[70205:14118946] 111
    

    rac_newTextChannel

    @interface RACChannelTerminal<ValueType> : RACSignal<ValueType> <RACSubscriber>
    
    - (instancetype)init __attribute__((unavailable("Instantiate a RACChannel instead")));
    
    // Redeclaration of the RACSubscriber method. Made in order to specify a generic type.
    - (void)sendNext:(nullable ValueType)value;
    
    @end
    
    #rac_newTextChannel效果跟rac_textSignal一样, 那么它有什么特别的用法呢?
    [[textField
            rac_newTextChannel]
            subscribeNext:^(NSString * _Nullable x) {
                
                NSLog(@"%@", x);
            }];
    
    #rac_newTextChannel双向绑定
        UITextField *textFieldA = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];
        
        textFieldA.center          = self.view.center;
        textFieldA.backgroundColor = [UIColor yellowColor];
        
        [self.view addSubview:textFieldA];
        
        UITextField *textFieldB = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];
        
        textFieldB.center          = CGPointMake(self.view.center.x, self.view.center.y + 50);
        textFieldB.backgroundColor = [UIColor yellowColor];
        
        [self.view addSubview:textFieldB];
        
        RACChannelTerminal *terminalA = [textFieldA rac_newTextChannel];
        RACChannelTerminal *terminalB = [textFieldB rac_newTextChannel];
        
        [terminalA subscribe:terminalB];
        [terminalB subscribe:terminalA];
    
    #运行可以看到, 改变textFieldA的值textFieldB的值也会跟着改变, 反过来也一样.
    
    #这里如果要实现双向绑定, 其实还有一个简单的方法:
    RACChannelTo(textFieldA, text) = RACChannelTo(textFieldB, text);
    

    如果我们不仅仅想让两个绑定对象之间的值简单的相等而已呢? 比如textFieldA的值是123的时候textFieldB的值要为321要怎么处理呢?
    这里我们先说一个一会用到的方法: map(映射)

    map方法,将会创建一个和原来一模一样的信号,只不过新的信号传递的值变为了block(value)。

    [[[textField
            rac_textSignal]
            map:^id _Nullable(NSString * _Nullable value) {
                
                if ([value isEqualToString:@"11"]) {
                    
                    return @"1";
                } else {
                    
                    return @"0";
                }
            }] subscribeNext:^(id  _Nullable x) {
                
                NSLog(@"%@", x);
            }];
    

    运行看看, 当我们输入1, 会打印0, 输入11的时候会打印1, 这里就是把传递的值从textField的text转变成为我们的1 和 0;

    那么要实现上面的123 到 321可以这样写:

        RACChannelTerminal *terminalA = [textFieldA rac_newTextChannel];
        RACChannelTerminal *terminalB = [textFieldB rac_newTextChannel];
        
        [[terminalA
            map:^id _Nullable(id  _Nullable value) {
                
                if ([value isEqualToString:@"123"]) {
                    
                    return @"321";
                }
                
                return value;
            }]
            subscribe:terminalB];
    
        [terminalB subscribe:terminalA];
    

    大家可以自己运行看看效果, 当textFieldA输入123的时候textFieldB会变为321

     RAC(self.sureBtn, enabled) = [RACSignal combineLatest:@[self.phoneTF.rac_textSignal, self.codeTF.rac_textSignal] reduce:^id (NSString *phoneNumber, NSString *code){
            @strongify(self);
            if (phoneNumber.length==11 && code.length==6) {
                self.sureBtn.alpha = 1;
                return @(YES);
            } else {
                self.sureBtn.alpha = 0.6;
                return @(NO);
            }
        }];
    

    UIActionSheet+RACSignalSupport.h

    #import <UIKit/UIKit.h>
    
    @class RACDelegateProxy;
    @class RACSignal<__covariant ValueType>;
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface UIActionSheet (RACSignalSupport)
    
    @property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy;
    
    - (RACSignal<NSNumber *> *)rac_buttonClickedSignal;
    
    @end
    

    rac_buttonClickedSignal

    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"RAC ActionSheet" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"OK" otherButtonTitles:@"Other", nil];
        
        [[actionSheet
            rac_buttonClickedSignal]
         subscribeNext:^(NSNumber * _Nullable x) {
             
             NSLog(@"%@", x);
         }];
        
        [actionSheet showInView:self.view];
      #运行看看, x是actionSheet上按钮的编号, 我们拿到编号就可以做响应的事件处理了.
    

    UIAlertView+RACSignalSupport.h

    @interface UIAlertView (RACSignalSupport)
    
    @property (nonatomic, strong, readonly) RACDelegateProxy *rac_delegateProxy;
    
    
    - (RACSignal<NSNumber *> *)rac_buttonClickedSignal;
    
    
    - (RACSignal<NSNumber *> *)rac_willDismissSignal;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"RAC" message:@"RAC Alert" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
        
        [[alert
            rac_buttonClickedSignal]
            subscribeNext:^(NSNumber * _Nullable x) {
                
                NSLog(@"click: x");
            }];
        
        [[alert
            rac_willDismissSignal]
            subscribeNext:^(NSNumber * _Nullable x) {
                
                NSLog(@"dismiss: %@", x);
            }];
        
        [alert show];
    

    UIControl+RACSignalSupport.h

    #import <UIKit/UIKit.h>
    
    @class RACSignal<__covariant ValueType>;
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface UIControl (RACSignalSupport)
    
    - (RACSignal<__kindof UIControl *> *)rac_signalForControlEvents:(UIControlEvents)controlEvents;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        
        [button setFrame:CGRectMake(0, 0, 100, 35)];
        [button setCenter:self.view.center];
        [button setBackgroundColor:[UIColor yellowColor]];
        [button setTitle:@"按钮" forState:UIControlStateNormal];
        
        [[button
            rac_signalForControlEvents:UIControlEventTouchUpInside]
            subscribeNext:^(__kindof UIControl * _Nullable x) {
                
                NSLog(@"点击了按钮");
                x.backgroundColor = [UIColor redColor];
            }];
        
        [self.view addSubview:button];
    

    UIDatePicker+RACSignalSupport.h

    #import <UIKit/UIKit.h>
    
    @class RACChannelTerminal<ValueType>;
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface UIDatePicker (RACSignalSupport)
    
    - (RACChannelTerminal<NSDate *> *)rac_newDateChannelWithNilValue:(nullable NSDate *)nilValue;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 160)];
        datePicker.center = self.view.center;
        datePicker.backgroundColor = [UIColor redColor];
        
        [self.view addSubview:datePicker];
        
        UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 180, 35)];
        textField.center = CGPointMake(self.view.center.x, self.view.center.y - 100);
        textField.backgroundColor = [UIColor yellowColor];
        
        [self.view addSubview:textField];
        
        
        RACChannelTerminal *datePickerTerminal = [datePicker rac_newDateChannelWithNilValue:[NSDate date]];
        RACChannelTerminal *textFieldTerminal  = [textField rac_newTextChannel];
        
        [[datePickerTerminal
            map:^id _Nullable(id  _Nullable value) {
                NSLog(@"%@", value);
                NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
                return [dateFormatter stringFromDate:value];
            }]
            subscribe:textFieldTerminal];
    
    截屏2021-03-19 下午2.46.31.png

    相关文章

      网友评论

        本文标题:RAC整理

        本文链接:https://www.haomeiwen.com/subject/rjqbcltx.html