RXSwift Binding在展开Optional值时返回意外发现的nil

时间:2017-12-29 09:00:00

标签: ios swift mvvm swift4 rx-swift

我是MVVM和RxSwift的初学者,我想在我的下一个项目中实现它。目前,我正在使用我的登录模块,一切看起来都不错,但是每次运行我的应用程序时,它都会在将文本字段绑定到我的ViewModel时触发错误说"意外发现nil,同时解包一个Optional值" 。

有人可以帮我摆脱它吗? 以下是我的表现方式:

class LoginViewController: UIViewController {
    @IBOutlet weak var emailTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!
    @IBOutlet weak var loginButton: UIButton!

    private var loginViewModel: UserLoginViewModel!
    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

         emailTextField.rx.text.orEmpty
            .bind(to: loginViewModel.emailAdd)
            .disposed(by: disposeBag) <---- Displays "Unexpectedly found nil while unwrapping an Optional value"

         passwordTextField.rx.text.orEmpty
            .bind(to: loginViewModel.password)
            .disposed(by: disposeBag) <---- Displays "Unexpectedly found nil while unwrapping an Optional value"
    }
}


/////loginProtocol

protocol loginProtocol {
    //MARK - Input
    var emailAdd: Variable<String> { get }
    var password: Variable<String> { get }
    var loginButtonDidTap:PublishSubject<Void>{ get }
    var loginActionResult: Driver<AutenticationStatus> { get }
}


/// VIEW MODEL
class UserLoginViewModel: loginProtocol {
    var emailAdd: Variable<String>
    var password: Variable<String>
    let loginButtonDidTap = PublishSubject<Void>()
    var loginActionResult:Driver<AutenticationStatus>

    init(apiService: API) {
        let emailV = Variable<String>("")
        let passwordV = Variable<String>("")
        emailAdd = emailV
        password = passwordV
        let usernameAndPassword = Observable.combineLatest(emailAdd.asObservable(), password.asObservable()) {
            ($0, $1)
        }

        loginActionResult = loginButtonDidTap.asObservable()
            .withLatestFrom(usernameAndPassword)
            .flatMapLatest { (emailAdd, password) in
                return apiService.login(email: emailAdd, password: password)
            }.asDriver(onErrorJustReturn:.error(.server))
    }
}

Here's the screenshot

谢谢。

2 个答案:

答案 0 :(得分:5)

在您的代码中,outlet或ViewModel可能为零。如果您的代码部分已完成,则永远不会创建loginViewModel

override func viewDidLoad() {
    super.viewDidLoad()

    // create view model
    loginViewModel = UserLoginViewModel(apiService: /* your api service */)

    emailTextField.rx.text.orEmpty
        .bind(to: loginViewModel.emailAdd)
        .disposed(by: disposeBag)

    passwordTextField.rx.text.orEmpty
        .bind(to: loginViewModel.password)
        .disposed(by: disposeBag)
}

答案 1 :(得分:-1)

我刚刚发现错误。 LoginViewModel未初始化。 我通过初始化loginViewModel修复了错误。这是我的工作方式

 var viewModel:LoginViewModel!
     override func viewDidLoad() {
            super.viewDidLoad()
            self.viewModel = LoginViewModel(apiService: APIManager.sharedManager)
        }