RAC雙向綁定UITextField的正確姿勢(shì)
一句話概括文章內(nèi)容
UITextField使用RACChannelTo的情況
- 問題描述
直接使用RACChannelTo實(shí)現(xiàn)
UITextField的雙向綁定是有隱患的
- 問題展示
// 使用RACChannelTo雙向綁定
RACChannelTo(self, string) = RACChannelTo(self.textField, text);
// 結(jié)果1:通過鍵盤給self.textField.text賦值的情況
// self.textField.text 改變 self.string 不改變
// self.string 改變 self.textField.text 改變
// 結(jié)果2:通過代碼給self.textField.text賦值的情況
eg: `self.textField.text = @"123";` // 通過代碼賦值
// self.textField.text 改變 self.string 改變
// self.string 改變 self.textField.text 改變
-
問題結(jié)論
使用
RACChannelTo(self.textField, text),
當(dāng)通過code改變self.textField. text的值的時(shí)候
才會(huì)把這個(gè)值發(fā)送出去
UITextField使用rac_newTextChannel的情況
- 問題描述
直接使用rac_newTextChannel實(shí)現(xiàn)
UITextField的雙向綁定是有隱患的
- 問題展示
// 使用rac_newTextChannel雙向綁定
RACChannelTo(self, string) = self.textField.rac_newTextChannel;
// 結(jié)果1:通過鍵盤給self.textField.text賦值的情況
// self.textField.text 改變 self.string 改變
// self.string 改變 self.textField.text 改變
// 結(jié)果2:通過代碼給self.textField.text賦值的情況
eg: `self.textField.text = @"123";` // 通過代碼賦值
// self.textField.text 改變 self.string 不改變
// self.string 改變 self.textField.text 改變
-
問題結(jié)論
使用
self.textField.rac_newTextChannel,
當(dāng)通過鍵盤改變self.textField. text的值的時(shí)候
才會(huì)把這個(gè)值發(fā)送出去
問題總結(jié)
無論是使用RACChannelTo還是rac_newTextChannel
self.string的值改變的時(shí)候,
self.textField.text都會(huì)跟著改變
也就是說
self.string -> self.textField.text 的這個(gè)單向通道是沒問題的
問題就在
無論是通過鍵盤或者code賦值來改變textField.text的值的時(shí)候,我們都要讓綁定的string對(duì)應(yīng)的改變,這才是我們要的雙向綁定
RACChannelTo |
rac_newTextChannel |
|---|---|
當(dāng)通過code改變self.textField.text的值的時(shí)候才會(huì)把這個(gè)值發(fā)送出去 |
當(dāng)通過鍵盤改變self.textField. text的值的時(shí)候才會(huì)把這個(gè)值發(fā)送出去 |
解決方案
- 錯(cuò)誤做法 --
rac_textSignal作祟導(dǎo)致
RACChannelTo(self, string) = self.textField.rac_newTextChannel;
此方式雙向綁定存在問題:通過code改變self.textField.text的值時(shí),不會(huì)發(fā)送值出去,導(dǎo)致綁定string失敗
因?yàn)槲覀冡槍?duì)這個(gè)痛點(diǎn)來解決
RACChannelTo(self, string) = self.textField.rac_newTextChannel;
@weakify(self);
// 當(dāng) self.textField.text改變的時(shí)候,會(huì)回調(diào)這個(gè)block,然后再給string賦值,實(shí)現(xiàn)雙向綁定
[self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
@strongify(self);
self.string = x;
}];
結(jié)果: 當(dāng)self.textField.text = @"12312";code賦值的時(shí)候,self.textField.rac_textSignal不會(huì)觸發(fā)回調(diào)
原因 是rac_textSignal這個(gè)signal是監(jiān)聽UIControlEventAllEditingEvents的,所以對(duì)setter方式不會(huì)觸發(fā)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的實(shí)現(xiàn),從中主要看到
concat:[self rac_signalForControlEvents:UIControlEventAllEditingEvents]]
// concat: 連接信號(hào),第一個(gè)信號(hào)必須發(fā)送完成,第二個(gè)信號(hào)才會(huì)被激活
// 也就是說,必須觸發(fā)UIControlEventAllEditingEvents才會(huì)觸發(fā)rac_textSignal,所以用setter的方式賦值就gg了
- 正確做法
RACChannelTo(self, string) = RACChannelTo(self.textField, text);
此方式雙向綁定存在問題:通過鍵盤改變self.textField.text的值時(shí),不會(huì)發(fā)送值出去,導(dǎo)致綁定string失敗
因?yàn)槲覀冡槍?duì)這個(gè)痛點(diǎn)來解決
RACChannelTo(self, string) = RACChannelTo(self.textField, text);
@weakify(self);
[self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
@strongify(self);
self.string = x;
}];
簡(jiǎn)化代碼
RACChannelTo(self, string) = RACChannelTo(self.textField, text);
[self.textField.rac_textSignal subscribe:RACChannelTo(self, string)];
結(jié)語
UITextView的情況及處理跟UITextField一樣
對(duì)于整篇文章雙向綁定的分析,主要圍繞三個(gè)點(diǎn)
-
string->textField.text - 鍵盤改變
textField.text->string - code賦值
textField.text->string
滿足上面三點(diǎn)就算完全的雙向綁定