swift - 对 MVVM 中的信号使用react?

标签 swift mvvm reactive-programming reactive-cocoa rx-swift

当我第一次设置登录 View 和使用 Reactive 编程时 - 我无法从我的 ViewContoller 生成信号,该信号将在我的 View 中使用包含我的表单的 Bool 提醒我的 observeValues 监听器验证:

查看文件

viewModel.outputs.loginSuccess
    .observeValues { [weak self] value in
        print(value)
}

使用我当前的代码 loginSuccess 每次更改电子邮件或密码文本字段时都会触发(我的 View 文件中有 .addTarget 更新我的 MutableProperites我的模型 View 文件)。我遇到麻烦的地方是为 tryLogin 创建一个信号,该信号仅在按下登录按钮时发出,然后映射我的表单验证( emailAndPassword.map(isValid) ),我可以在我的 View 文件中回复。

模型 View 文件

import ReactiveCocoa
import ReactiveSwift
import Result

public protocol LoginViewModelInputs {

    /// String value of email textfield text
    func emailChanged(_ email: String?)

    /// String value of password textfield text
    func passwordChanged(_ password: String?)

    /// Call when login button is pressed.
    func loginButtonTapped()
}

public protocol LoginViewModelOutputs {

    /// Emits on login.
    var loginSuccess: Signal<(Bool), NoError> { get }
}

public protocol LoginViewModelType {
    var inputs: LoginViewModelInputs { get }
    var outputs: LoginViewModelOutputs { get }
}

public final class LoginViewModel: LoginViewModelType, LoginViewModelInputs,     LoginViewModelOutputs {

    public init() {

        let emailAndPassword = Signal.combineLatest(
            self.emailChangedProperty.signal.skipNil(),
            self.passwordChangedProperty.signal.skipNil()
        )

        let tryLogin = loginButtonTappedProperty.map {
            emailAndPassword.map(isValid)
        }

        self.loginSuccess = tryLogin.value
    }

    fileprivate let emailChangedProperty = MutableProperty<String?>(nil)
    public func emailChanged(_ email: String?) {
        self.emailChangedProperty.value = email
    }
    fileprivate let loginButtonTappedProperty = MutableProperty()
    public func loginButtonTapped() {
        self.loginButtonTappedProperty.value = ()
    }
    fileprivate let passwordChangedProperty = MutableProperty<String?>(nil)
    public func passwordChanged(_ password: String?) {
        self.passwordChangedProperty.value = password
    }

    public let loginSuccess: Signal<(Bool), NoError>

    public var inputs: LoginViewModelInputs { return self }
    public var outputs: LoginViewModelOutputs { return self }
}

func isValid(email: String, password: String) -> Bool {
    return !email.characters.isEmpty && !password.characters.isEmpty
}

感谢任何帮助。我没有找到很多好的文档来了解信号或观察者,但我可能没找对地方。

最佳答案

这是我会采取的方法

  • 根据用户名和密码输入的验证启用和禁用 loginButton
  • 将登录 Action 绑定(bind)到按钮事件

代码如下:

let usernameField: UITextField
let passwordField: UITextField
let loginEnabled: MutableProperty<Bool>
let loginButton: UIButton

loginEnabled <~
    Signal.combineLatest(
        usernameField.reactive.controlEvents(.allEditingEvents),
        passwordField.reactive.controlEvents(.allEditingEvents))
    .map { _ -> Bool in
        return validation()
    }

// only allow button to be pressed when validation succeeds
loginButton.reactive.isEnabled <~ loginEnabled

// login action
let loginAction = Action<(String?,String?),Void,NoError> { (username, password) -> SignalProducer<Void, NoError> in
    // replace with login procedure
    return SignalProducer.empty
}

// bind button event to login action
loginButton.reactive.pressed = CocoaAction(loginAction, input: 
    (usernameField.text, passwordField.text))

关于swift - 对 MVVM 中的信号使用react?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43032682/

相关文章:

reactive-programming - 如何在 Project Reactor 3 中将冷流转换为热流?

ios - SwiftUI如何知道将哪个environmentObject分配给哪个变量

wpf - PRISM + MEF + MVVM——不确定从哪里开始?

swift - 稍微延迟编辑文本字段

ios - iOS 上 GMUClusterRenderer(谷歌地图集群)的滚动/缩放体验非常慢

silverlight - 我应该在 Silverlight 项目中使用模型- View - View 模型 (MVVM) 模式吗?

multithreading - 如果消息队列关闭,如何在事件驱动微服务中处理?

java - 在 rxjava 中使用一系列 Observable 进行一对多映射

ios - 测试应用内购买(IAP)-需要帮助来清除交易队列

swift - 如何使用包标识符将系统首选项启动到特定首选项 Pane ?