मैं आरएक्सस्विफ्ट के लिए नया हूं और एमवीवीएम इनपुट आउटपुट दृष्टिकोण के साथ शीर्षक राज्यों के रूप में करने का प्रयास कर रहा हूं।
मैं निम्नलिखित करने के लिए सबसे अच्छा तरीका नहीं समझ सकता।
- सबमिट बटन टैप किए जाने पर फ़ोन नंबर टेक्स्ट फ़ील्ड मानों को मान्य करें
- अगर फोन नम्बर टेक्स्टफिल्ड अमान्य है और क्लाइंट साइड एरर फेंक दें तो अलामोफायर रिक्वेस्ट को सबमिट होने से रोकें
- लोडिंग होने पर डिस्प्ले इंडिकेटर दिखाएं। यह अभी सबसे कम महत्वपूर्ण है
ध्यान देने योग्य कुछ बातें।
- इस समय फ़ोन नंबर टेक्स्ट को ट्रैक करने वाला कुछ भी नहीं है
- मैं सबमिट बटन को तब तक अक्षम नहीं करना चाहता जब तक कि फॉर्म मान्य न हो जैसा कि सभी उदाहरणों में देखा गया है।
यहाँ मेरा व्यू कंट्रोलर है
import UIKit
import RxSwift
import RxCocoa
class SplashViewController: BaseViewController {
// MARK: – View Variables
@IBOutlet weak var phoneNumberTextField: UITextField!
@IBOutlet weak var phoneNumberBackgroundView: UIView!
@IBOutlet weak var submitButton: BaseButton!
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var separatorView: UIView!
@IBOutlet weak var countryCodeButton: UIButton!
@IBOutlet weak var parentVerticalStackView: UIStackView!
// MARK: – View Model & RxSwift Setup
private let disposeBag = DisposeBag()
private let viewModel: SplashMVVM = SplashMVVM()
// MARK: – View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
// RxSwift handling
setupViewModelBinding()
setupCallbacks()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: true)
}
// MARK: – RxSwift Handling
private func setupViewModelBinding() {
submitButton.rx.controlEvent(.touchUpInside)
.bind(to: viewModel.input.submit)
.disposed(by: disposeBag)
}
private func setupCallbacks() {
viewModel.output.success.asObservable()
.filter { $0 != nil }
.observeOn(MainScheduler())
.subscribe({ _ in
self.pushVerifyPhoneNumberViewController()
})
.disposed(by: disposeBag)
viewModel.output.error.asObservable()
.filter { $0 != nil }
.observeOn(MainScheduler())
.subscribe({ _ in
SwiftMessages.show(.error, message: "There was an error. Please try again.")
})
.disposed(by: disposeBag)
}
// MARK: – Navigation
func pushVerifyPhoneNumberViewController() {
let viewController = VerifyPhoneNumberViewController.fromStoryboard("Authentication")
self.navigationController?.pushViewController(viewController, animated: true)
}
}
यहाँ मेरा दृश्य मॉडल है।
import Foundation
import RxSwift
import RxCocoa
import Alamofire
final class SplashMVVM: InputOutputModelType {
let input: SplashMVVM.Input
let output: SplashMVVM.Output
var submitSubject = PublishSubject<Void>()
struct Input {
let submit: AnyObserver<Void>
}
struct Output {
let success: Observable<VerifyMobilePhone?>
let error: Observable<Error?>
}
init() {
input = Input(submit: submitSubject.asObserver())
let request = Alamofire.request(VerifyMobileRouter.post("+16306996540")).responseDecodableRx(VerifyMobilePhone.self)
let requestData = submitSubject.flatMapLatest {
request
}
let success = requestData.map { $0.value ?? nil }
let error = requestData.map { $0.error ?? nil }
output = Output(
success: success,
error: error
)
}
}
यहां वह है जो मैंने जुटाया।
final class SplashMVVM: InputOutputModelType {
let input: SplashMVVM.Input
let output: SplashMVVM.Output
var submitSubject = PublishSubject<Void>()
var phoneNumberSubject = PublishSubject<String>()
struct Input {
let phoneNumber: AnyObserver<String>
let submit: AnyObserver<Void>
}
struct Output {
let validationError: Observable<String>
let success: Observable<VerifyMobilePhone>
let error: Observable<Error>
}
init() {
input = Input(phoneNumber: phoneNumberSubject.asObserver(), submit: submitSubject.asObserver())
let request = submitSubject.asObservable().withLatestFrom(phoneNumberSubject.asObservable()).filter {
$0.isValidPhoneNumber(region: "US")
}.flatMap { number in
Alamofire.request(VerifyMobileRouter.post(number)).responseDecodableRx(VerifyMobilePhone.self)
}.share()
let validationError = submitSubject.asObservable().withLatestFrom(phoneNumberSubject.asObservable()).filter {
!$0.isValidPhoneNumber(region: "US")
}.map { _ in
"This phone number is invalid"
}
let success = request.filter { $0.isSuccess }.map { $0.value! }
let error = request.filter { $0.isFailure }.map { $0.error! }
output = Output(
validationError: validationError,
success: success,
error: error
)
}
}
नियंत्रक परिवर्तन देखें…
private func setupViewModelBinding() {
submitButton.rx.controlEvent(.touchUpInside).bind(to: viewModel.input.submit).disposed(by: disposeBag)
phoneNumberTextField.rx.text.orEmpty.bind(to: viewModel.input.phoneNumber).disposed(by: disposeBag)
}
private func setupCallbacks() {
viewModel.output.validationError.bind { string in
SwiftMessages.show(.error, message: string)
}.disposed(by: disposeBag)
viewModel.output.success.bind { verifyMobilePhone in
self.pushVerifyPhoneNumberViewController()
}.disposed(by: disposeBag)
viewModel.output.error.bind { error in
SwiftMessages.show(.error, message: "There was an error. Please try again.")
}.disposed(by: disposeBag)
}
1 उत्तर
आप करीब हैं, आप अपने व्यू मॉडल में इनपुट के रूप में फोन नंबर टेक्स्ट खो रहे हैं।
struct SplashInput {
let phoneNumber: Observable<String>
let submit: Observable<Void>
}
struct SplashOutput {
let invalidInput: Observable<Void>
let success: Observable<VerifyMobilePhone>
let error: Observable<Error>
}
extension SplashOutput {
init(_ input: SplashInput) {
let request: Observable<Event<VerifyMobilePhone>> = input.submit.withLatestFrom(input.phoneNumber)
.filter { $0.isValidPhoneNumber }
.flatMap { number in
Alamofire.request(VerifyMobileRouter.post(number)).responseDecodableRx(VerifyMobilePhone.self)
.materialize()
}
.share()
invalidInput = input.submit.withLatestFrom(input.phoneNumber)
.filter { $0.isValidPhoneNumber == false }
success = request
.map { $0.element }
.filter { $0 != nil }
.map { $0! }
error = request
.map { $0.error }
.filter { $0 != nil }
.map { $0! }
}
}
आपके SplashViewController
के पास होगा:
override func viewDidLoad() {
super.viewDidLoad()
let input = SplashInput(
phoneNumber: phoneNumberTextField.rx.text.orEmpty.asObservable(),
submit: submitButton.rx.tap.asObservable()
)
let viewModel = SplashOutput(input)
viewModel.invalidInput
.bind {
SwiftMessages.show(.invalid, message: "You entered an invalid number. Please try again.")
}
.disposed(by: bag)
viewModel.success
.bind { [unowned self] verifyMobilePhone in
self.pushVerifyPhoneNumberViewController(verifyMobilePhone)
}
.disposed(by: bag)
viewModel.error
.bind { error in
SwiftMessages.show(.error(error), message: "There was an error. Please try again.")
}
}
(जो आपने पहले ही लिखा है, उसके साथ मैंने कुछ स्वतंत्रता ली है, लेकिन उपरोक्त को समझ में आना चाहिए।)
संबंधित सवाल
नए सवाल
ios
iOS, Apple iPhone, iPod टच और iPad पर चलने वाला मोबाइल ऑपरेटिंग सिस्टम है। IOS प्लेटफॉर्म पर प्रोग्रामिंग से संबंधित प्रश्नों के लिए इस टैग [ios] का उपयोग करें। उन प्रोग्रामिंग भाषाओं के लिए विशिष्ट मुद्दों के लिए संबंधित टैग [उद्देश्य-सी] और [स्विफ्ट] का उपयोग करें।