在使用 RxSwift 和 mvvm 发出 moya 请求时添加微调器,并在用户收到响应时将其关闭

Posted

技术标签:

【中文标题】在使用 RxSwift 和 mvvm 发出 moya 请求时添加微调器,并在用户收到响应时将其关闭【英文标题】:Add a spinner on making a moya request using RxSwift and mvvm and dismiss it when user receives a response 【发布时间】:2017-11-03 10:14:26 【问题描述】:

我有一个应用程序,我正在尝试使用 MVVM 实现 RxSwift。

我有 SignInViewModel,我在其中进行验证,并且我正在使用我正在收听的其余响应布尔值更新登录 observable。

在控制器类中,只要验证通过,登录按钮就会启用。

以类似的方式,我希望能够在单击按钮时启动微调器,并在用户收到响应时关闭。

当我尝试从控制器类的视图模型中监听 loginObservable 时。它没有命中绑定块。

我无法弄清楚问题所在。

任何帮助将不胜感激

以下是我的 SignInViewModel

class SignInViewModel 

    let validatedEmail: Observable<Bool>
    let validatedPassword: Observable<Bool>
    let loginEnabled: Observable<Bool>
    let loginObservable: Observable<Bool>

    init(username: Observable<String>,
         password: Observable<String>,
         loginTap: Observable<Void>) 

        self.validatedEmail = username
            .map  $0.characters.count >= 5 
            .shareReplay(1)

        self.validatedPassword = password
            .map  $0.characters.count >= 2 
            .shareReplay(1)

        self.loginEnabled = Observable.combineLatest(validatedEmail, validatedPassword )  $0 && $1 
        let userAndPassword = Observable.combineLatest(username, password) ($0,$1)

        self.loginObservable = loginTap.withLatestFrom(userAndPassword).flatMapLatest (username, password) in
            return RestService.login(username: username, password: password).observeOn(MainScheduler.instance)
        
    

下面是 moyaRequest 类

final class MoyaRequest
    func signIn(userData: Creator) -> Observable<Response> 
            return provider.request(.signIn(userData))
                .filter(statusCode: 200)
        

下面是我的 RestService 类

class RestService:NSObject 

    static var moyaRequest = MoyaRequest()
    static var disposeBag = DisposeBag()

static func login(username: String, password: String) -> Observable<Bool> 
    let userData = Creator()
    userData?.username = username
    userData?.password = password
    print("Username password", userData?.username, userData?.password)
    return  Observable.create  observer in moyaRequest.signIn(userData: userData!).subscribe event -> Void in
        switch event 

        case .next(let response):
            print("Response",response)

        case .error(let error):
            let moyaError: MoyaError? = error as? MoyaError
            let response: Response? = moyaError?.response
            let statusCode: Int? = response?.statusCode

            print("Sample Response code error" + String(describing: statusCode))
        default:
            break
        
        
        return Disposables.create()
    


我正在尝试在控制器类中绑定视图模型。

class SignInViewController: UIViewController

    let disposeBag = DisposeBag()
    @IBOutlet weak var passwordTextfield: UITextField!
    @IBOutlet weak var usernameTextfield: UITextField!

    private var viewModel : SignInViewModel!
    @IBOutlet weak var signInButton: UIButton!
    override func viewDidLoad() 
        setUpRxViewModel()

    

    func setUpRxViewModel()
        self.viewModel = SignInViewModel(username: self.usernameTextfield.rx.text.orEmpty.asObservable(),
                                         password: self.passwordTextfield.rx.text.orEmpty.asObservable(),
                                         loginTap: self.signInButton.rx.tap.asObservable())

        self.viewModel.loginEnabled.bind valid  in
            self.signInButton.isEnabled = valid
            .addDisposableTo(disposeBag)

        self.viewModel.loginObservable.bind input in
            print("Login Clicked")
            .addDisposableTo(disposeBag)


    

【问题讨论】:

【参考方案1】:

在您的login 方法中,您没有向观察者发送任何事件。应该是:

case .next(let response):
            observer.on(.next(true))
            print("Response",response)

case .error(let error):
            observer.on(.error(error))
            //or observer.on(.next(false)) if you intend to use Bool as indicator of operation success which is a very bad idea.
            let moyaError: MoyaError? = error as? MoyaError
            let response: Response? = moyaError?.response
            let statusCode: Int? = response?.statusCode

此外,如果您将 Moya 与 RxSwift 一起使用,我建议您在任何地方使用 RxMoyaProvider。使用Observable.create 通常意味着你做错了什么。

您也不应该在网络请求级别根据状态代码过滤事件,因为如果出现问题,您将不会在链中收到任何事件。

【讨论】:

我正在使用 RxMoyaProvider。 .如果我不使用 Observable.create 该函数将返回错误。如何在不使用 Observable.create 的情况下让它工作?

以上是关于在使用 RxSwift 和 mvvm 发出 moya 请求时添加微调器,并在用户收到响应时将其关闭的主要内容,如果未能解决你的问题,请参考以下文章

传递数据 MVVM 和 RxSwift

RxSwift 和 MVVM:observable 在没有绑定的情况下无法执行

如何使用 MVVM 和 RxSwift 编辑/删除 UICollectionView 单元格

如何在MVVM架构中使用RxSwift发送参数来查看模型?

用于搜索屏幕的 MVVM 和 RxSwift

RxSwift(24)——MVVM双向绑定