如何使用 ReactiveCocoa 处理无效令牌

How to handle invalid token using ReactiveCocoa

我想知道处理来自服务器的无效令牌的正确方法是什么。

  1. 我想到的第一个解决方案是在 ViewModel 层启动一个事件,在 rootViewController 导航到登录页面时监听该事件。

  2. 第二种方案(第一种方案可行,但我真的不喜欢事件,我想用信号而不是事件),在rootViewController中添加一个authenticationViewModel,订阅invalidToken(或者叫它注销)视图层中的信号)rootViewController 中的信号,api 调用中的触发信号。

请问,请问有没有更好的办法处理?

该示例基于 RAC3,我不知道这是否是最佳解决方案,但这是我经过一些试验后得出的结果。

我将身份验证令牌作为 MutableProperty 存储在视图模型中,并在视图控制器中观察有效和无效令牌。

像这样:

查看模型:

class LoginViewModel {

    let username = MutableProperty<String>("")
    let password = MutableProperty<String>("")
    let authToken = MutableProperty<String>("")
    let invalidToken = MutableProperty<String>("")
    private let _inputValid = MutableProperty(false)

    var action:Action<AnyObject?, String, NSError>?
    var cocoaAction:CocoaAction?

    init() {
       let validation: Signal<String, NoError> -> Signal<Bool, NoError> = map { string in
           return count(string) > 0
       }

       _inputValid <~ combineLatest(
           username.producer
              |> validation,
           password.producer
              |> validation)
        |> map({ user, pass in return user && pass })

        action = Action(enabledIf:_inputValid) { _ in
            return LoginService().login(self.username.value, password: self.password.value) }
        cocoaAction = CocoaAction(action!, input: nil)
        action!.values.observe(next: { self.authToken.put([=10=]) })
        action!.errors.observe(next: { self.invalidToken.put([=10=])})
   }
}

在ViewController中可以观察到authToken和invalidToken:

viewModel.authToken.producer
    |> filter { count([=11=]) > 0 }
    |> start(next: {
        _ in
            // do something in case token is ok 
    })

viewModel.invalidToken.producer
    |> filter { count([=11=]) > 0 }
    |> start(next: {
        _ in
            // do something in case token is NOT ok 
    })

如果您的用户名和密码是文本字段,您可以像这样将输入映射到对应的视图模型

viewModel.username <~ userNameTextField.rac_textSignal().toSignalProducer() |> map { [=12=] as? String ?? "" } |> catch { _ in SignalProducer<String, NoError>.empty }
viewModel.password <~ passwordTextField.rac_textSignal().toSignalProducer() |> map { [=12=] as? String ?? "" } |> catch { _ in SignalProducer<String, NoError>.empty }