【问题标题】:Rxswift validate inputs before sending api requestRxswift 在发送 api 请求之前验证输入
【发布时间】:2019-07-12 21:22:25
【问题描述】:

我有一个登录屏幕,我之前在文本字段上方显示错误输入并通过组合电子邮件/密码 Bool Observable 禁用按钮,但是现在设计已更改,我想在发送请求之前检查电子邮件/密码是否不为空或显示警报对话框

我的问题是如何在发出请求之前验证输入是否有效:

登录视图模型:

  var emailValid: Observable<Bool> {
        return emailSubject.asObservable().map { $0.count > 0 && $0.isEmail}
    }

  signInDidTapSubject
       .withLatestFrom(credentialsObservable)
        .flatMapLatest { credentials -> Observable<Event<Result<UserResponse>>> in
            self.loadInProgress.accept(true)
            return network.login(with: credentials).materialize()
        }
        .subscribe(onNext: { [weak self] event in
            self?.loadInProgress.accept(false)
            switch event {
            case .next(let result):
                switch result{
                case .Success(let user):
                    self?.loginResultSubject.onNext(user)
                case .Failure(let error):
                    self?.errorsSubject.onNext(error)
                }
            case .error( _):
                print("error")
            default:
                break
            }
        })
        .disposed(by: disposeBag)

VC:

   loginButton.rx.tap.asObservable()
        .debounce(0.5, scheduler: MainScheduler.instance)
        .subscribe(viewModel.input.loginButtonTapped).disposed(by: disposeBag)

【问题讨论】:

    标签: swift mvvm observable rx-swift


    【解决方案1】:

    你解决这个问题的方法是问自己,“我需要什么输入来产生这个输出?”

    这里有两个输出“用户”和“错误”。让我们先走幸福的道路。产生用户需要哪些输入?只是一个成功的网络响应。但是您需要哪些输入来产生网络响应?好吧,您需要电子邮件和密码,但触发事件是点击登录按钮,如果数据无效,则不应发出请求:

    let networkResponse = loginTrigger
        .withLatestFrom(credentials)
        .filter { $0.email.isEmail && !$0.password.isEmpty }
        .flatMapLatest {
            network.login(with: $0)
                .materialize()
        }
        .share(replay: 1)
    
    let user = networkResponse
        .filter { $0.element != nil }
        .map { $0.element! }
    

    现在,您需要哪些输入来生成错误输出?如果有,则需要网络请求中的错误,并且您需要知道电子邮件或密码是否无效。但是,如果点击登录按钮,您只想知道无效输入...

    这很多,但它是如何分解的:

    let networkError = networkResponse
        .filter { $0.error != nil }
        .map { $0.error! }
    
    let invalidEmailError = loginTrigger
        .withLatestFrom(email)
        .filter { !$0.isEmail }
        .map { _ in UIError.badEmail as Error }
    
    let invalidPasswordError = loginTrigger
        .withLatestFrom(password)
        .filter { $0.isEmpty }
        .map { _ in UIError.badPassword as Error }
    
    let error = Observable.merge(networkError, invalidEmailError, invalidPasswordError)
    

    看看效果如何?依次获取每个输出,并找出使该输出起作用所需的输入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多