在我第一次设置登录视图并使用Reactive编程时 - 我无法从我的ViewContoller生成一个Signal,它会在我的视图中通过包含我的表单验证的Bool警告我的observeValues
侦听器:< / p>
查看文件
viewModel.outputs.loginSuccess
.observeValues { [weak self] value in
print(value)
}
每次更改电子邮件或密码文本字段时,我的当前代码loginSuccess
都会触发(我的视图文件中有.addTarget
,我的模型视图文件中的MutableProperites更新)。我遇到问题的地方是为tryLogin
创建一个仅在按下登录按钮时发出的信号,然后映射我的表单验证(emailAndPassword.map(isValid)
),我可以在我的视图文件中对其进行响应。 / p>
模型视图文件
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
}
感谢任何帮助。我没有找到很多关于信号或观察者的好文档,但我可能没有找到合适的位置。
答案 0 :(得分:1)
Here是使用RAC构建的输入表单的示例。
它有点过时了 - 本例中以rex_
开头的所有内容(这是UI绑定的外部扩展库,现在直接集成到RAC中)现在更改为.reactive.
< / p>
UITextField.rex_textSignal
现在是UITextField.reactive.continuousTextValues
UIButton.rex_pressed
现在是UIButton.reactive.pressed
您可以实施实际的身份验证操作,而不是将凭据保存到NSUserDefaults
中的authenticationAction
。
BTW:您永远不应将用户凭据(尤其是密码)保存到NSUserDefaults
。请改用钥匙串!
关键点是
MutableProperty
来存储当前输入值.reactive
属性和绑定操作符<~
将viewModel绑定到输入(viewModel.attribute <~ textField.reactive.continuouseTextValues
)Action
按需执行实际工作Action
(CocoaAction
)button.reactive.pressed = CocoaAction(viewModel.loginAction)
绑定到UIControl
希望能帮到你!
答案 1 :(得分:1)
以下是我采取的方法
以下是代码:
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))