मैं RxSwift के साथ एक एमवीवीएम लिखने की कोशिश कर रहा हूं और उद्देश्य-सी के लिए प्रतिक्रियाशील कोको में जो कुछ भी करने के लिए उपयोग किया गया था उसकी तुलना करना, मेरी सेवा को सही तरीके से लिखना थोड़ा मुश्किल रहा है।RxSwift सही तरीका
एक उदाहरण एक लॉगिन सेवा है।
ReactiveCocoa (ऑब्जेक्टिव-सी) इस तरह मैं कोड कुछ के साथ:
// ViewController
// send textfield inputs to viewmodel
RAC(self.viewModel, userNameValue) = self.fieldUser.rac_textSignal;
RAC(self.viewModel, userPassValue) = self.fieldPass.rac_textSignal;
// set button action
self.loginButton.rac_command = self.viewModel.loginCommand;
// subscribe to login signal
[[self.viewModel.loginResult deliverOnMainThread] subscribeNext:^(NSDictionary *result) {
// implement
} error:^(NSError *error) {
NSLog(@"error");
}];
और मेरे ViewModel इस तरह होना चाहिए:
// valid user name signal
self.isValidUserName = [[RACObserve(self, userNameValue)
map:^id(NSString *text) {
return @(text.length > 4);
}] distinctUntilChanged];
// valid password signal
self.isValidPassword = [[RACObserve(self, userPassValue)
map:^id(NSString *text) {
return @(text.length > 3);
}] distinctUntilChanged];
// merge signal from user and pass
self.isValidForm = [RACSignal combineLatest:@[self.isValidUserName, self.isValidPassword]
reduce:^id(NSNumber *user, NSNumber *pass){
return @([user boolValue] && [pass boolValue]);
}];
// login button command
self.loginCommand = [[RACCommand alloc] initWithEnabled:self.isValidForm
signalBlock:^RACSignal *(id input) {
return [self executeLoginSignal];
}];
अब RxSwift में मैं के रूप में ही लिखा है:
// ViewController
// initialize viewmodel with username and password bindings
viewModel = LoginViewModel(withUserName: usernameTextfield.rx_text.asDriver(), password: passwordTextfield.rx_text.asDriver())
// subscribe to isCredentialsValid 'Signal' to assign button state
viewModel.isCredentialsValid
.driveNext { [weak self] valid in
if let button = self?.signInButton {
button.enabled = valid
}
}.addDisposableTo(disposeBag)
// signinbutton
signInButton.rx_tap
.withLatestFrom(viewModel.isCredentialsValid)
.filter { $0 }
.flatMapLatest { [unowned self] valid -> Observable<AutenticationStatus> in
self.viewModel.login(self.usernameTextfield.text!, password: self.passwordTextfield.text!)
.observeOn(SerialDispatchQueueScheduler(globalConcurrentQueueQOS: .Default))
}
.observeOn(MainScheduler.instance)
.subscribeNext {
print($0)
}.addDisposableTo(disposeBag)
मैं बटन राज्य इस तरह से बदल रहा हूँ क्योंकि मैं यह काम करने के लिए नहीं कर सकते हैं:
viewModel.isCredentialsValid.drive(self.signInButton.rx_enabled).addDisposableTo(disposeBag)
और मेरे ViewModel
let isValidUser = username
.distinctUntilChanged()
.map { $0.characters.count > 3 }
let isValidPass = password
.distinctUntilChanged()
.map { $0.characters.count > 2 }
isCredentialsValid = Driver.combineLatest(isValidUser, isValidPass) { $0 && $1 }
और
func login(username: String, password: String) -> Observable<AutenticationStatus>
{
return APIServer.sharedInstance.login(username, password: password)
}
मैं ड्राइवर का उपयोग कर रहा है क्योंकि यह जैसे कुछ अच्छा सुविधाओं लपेट: catchErrorJustReturn(), लेकिन मैं वास्तव में पसंद नहीं है जिस तरह से मैं यह कर रहा हूं:
1) मुझे देखने के लिए पैरामीटर के रूप में उपयोगकर्ता नाम और पासवर्ड फ़ील्ड भेजना है मॉडल (वैसे, हल करने में आसान है)
2) मुझे पसंद नहीं है कि मेरा व्यू कंट्रोलर लॉग इन बटन टैप होने पर सभी काम करता है, देखें नियंत्रक को यह जानने की आवश्यकता नहीं है कि लॉगिन सेवा प्राप्त करने के लिए उसे कौन सी सेवा कॉल करनी चाहिए, यह है एक दृश्य मॉडल नौकरी।
3) मैं सदस्यता के बाहर उपयोगकर्ता नाम और पासवर्ड के संग्रहीत मूल्य तक नहीं पहुंच सकता।
क्या ऐसा करने का कोई अलग तरीका है? आप इस तरह की चीज कैसे कर रहे हैं? बहुत बहुत धन्यवाद।