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对应的改变,这才是我们要的双向绑定

RACChannelTorac_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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值