美文网首页iOS Development零碎知识点MVVM. RAC
RAC双向绑定UITextField的正确姿势

RAC双向绑定UITextField的正确姿势

作者: Corbin___ | 来源:发表于2018-03-05 11:13 被阅读111次

    RAC双向绑定UITextField的正确姿势


    一句话概括文章内容

    UITextField使用RACChannelTo的情况

    • 问题描述

    直接使用RACChannelTo实现
    UITextField的双向绑定是有隐患的

    • 问题展示
        // 使用RACChannelTo双向绑定
        RACChannelTo(self, string) = RACChannelTo(self.textField, text);
        
        // 结果1:通过键盘给self.textField.text赋值的情况
        // self.textField.text 改变 self.string 不改变
        // self.string 改变 self.textField.text 改变
        
        // 结果2:通过代码给self.textField.text赋值的情况
        eg: `self.textField.text = @"123";` // 通过代码赋值
        // self.textField.text 改变 self.string 改变
        // self.string 改变 self.textField.text 改变
        
    
    • 问题结论

      使用RACChannelTo(self.textField, text)
      当通过code改变self.textField. text的值的时候
      才会把这个值发送出去


    UITextField使用rac_newTextChannel的情况

    • 问题描述

    直接使用rac_newTextChannel实现
    UITextField的双向绑定是有隐患的

    • 问题展示
        // 使用rac_newTextChannel双向绑定
        RACChannelTo(self, string) = self.textField.rac_newTextChannel;
        
        // 结果1:通过键盘给self.textField.text赋值的情况
        // self.textField.text 改变 self.string 改变
        // self.string 改变 self.textField.text 改变
        
        // 结果2:通过代码给self.textField.text赋值的情况
        eg: `self.textField.text = @"123";` // 通过代码赋值
        // self.textField.text 改变 self.string 不改变
        // self.string 改变 self.textField.text 改变
        
    
    • 问题结论

      使用self.textField.rac_newTextChannel
      当通过键盘改变self.textField. text的值的时候
      才会把这个值发送出去


    问题总结

    无论是使用RACChannelTo还是rac_newTextChannel

    self.string的值改变的时候,

    self.textField.text都会跟着改变

    也就是说

    self.string -> self.textField.text 的这个单向通道是没问题的

    问题就在
    无论是通过键盘或者code赋值来改变textField.text的值的时候,我们都要让绑定的string对应的改变,这才是我们要的双向绑定

    RACChannelTo rac_newTextChannel
    当通过code改变self.textField.text的值的时候才会把这个值发送出去 当通过键盘改变self.textField. text的值的时候才会把这个值发送出去

    解决方案

    • 错误做法 -- rac_textSignal作祟导致

    RACChannelTo(self, string) = self.textField.rac_newTextChannel;

    此方式双向绑定存在问题:通过code改变self.textField.text的值时,不会发送值出去,导致绑定string失败

    因为我们针对这个痛点来解决

        
         RACChannelTo(self, string) = self.textField.rac_newTextChannel;
        @weakify(self);
        // 当 self.textField.text改变的时候,会回调这个block,然后再给string赋值,实现双向绑定
        [self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
            @strongify(self);
            self.string = x;
        }];
    
    

    结果:self.textField.text = @"12312";code赋值的时候,self.textField.rac_textSignal不会触发回调

    原因rac_textSignal这个signal是监听UIControlEventAllEditingEvents的,所以对setter方式不会触发signal(setter方式就是 属性A = @"123"

    - (RACSignal *)rac_textSignal {
       @weakify(self);
       return [[[[[RACSignal
           defer:^{
               @strongify(self);
               return [RACSignal return:self];
           }]
           concat:[self rac_signalForControlEvents:UIControlEventAllEditingEvents]]
           map:^(UITextField *x) {
               return x.text;
           }]
           takeUntil:self.rac_willDeallocSignal]
           setNameWithFormat:@"%@ -rac_textSignal", self.rac_description];
    }
    
    

    rac_textSignal的实现,从中主要看到

     
    concat:[self rac_signalForControlEvents:UIControlEventAllEditingEvents]]
    
    // concat: 连接信号,第一个信号必须发送完成,第二个信号才会被激活
    // 也就是说,必须触发UIControlEventAllEditingEvents才会触发rac_textSignal,所以用setter的方式赋值就gg了
    

    • 正确做法

    RACChannelTo(self, string) = RACChannelTo(self.textField, text);

    此方式双向绑定存在问题:通过键盘改变self.textField.text的值时,不会发送值出去,导致绑定string失败

    因为我们针对这个痛点来解决

        
        RACChannelTo(self, string) = RACChannelTo(self.textField, text);
        @weakify(self);
        [self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
            @strongify(self);
            self.string = x;
        }];
    
    

    简化代码

        RACChannelTo(self, string) = RACChannelTo(self.textField, text);
        [self.textField.rac_textSignal subscribe:RACChannelTo(self, string)];
    

    结语

    UITextView的情况及处理跟UITextField一样
    对于整篇文章双向绑定的分析,主要围绕三个点

    • string -> textField.text
    • 键盘改变textField.text -> string
    • code赋值textField.text -> string

    满足上面三点就算完全的双向绑定

    相关文章

      网友评论

      • 6ac8dc2cec33:cell 上RACChannelTo(self, string) = RACChannelTo(self.textField, text); 刷新会崩溃
        Corbin___:这个有点忘了,好久没搞RAC了

      本文标题:RAC双向绑定UITextField的正确姿势

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