2

I've just started playing around with Rx and decided to try out making a simple OSX app using RxSwift.

Since my app has a login form, I've found that GithubSignup example is pretty similar to what I'm doing.

I'm, however having an issue that my Drivers get disposed after first value is emitted from them, and I can't figure out how or why. Since my code is really similar to one from the Github example, I must be overlooking something.

Here is my ViewModel:

class LoginVM {

    let isWorking: Driver<Bool>
    let loginEnabled: Driver<Bool>

    init(
        input: (
            email: Driver<String>,
            password: Driver<String>,
            loginRequests: Driver<Void>
        ),
        dependency: (
            RoundedClient
        )
    ) {
        self.isWorking = Variable(false).asDriver()

        let credentials = Driver
            .combineLatest(input.email, input.password){ (email: $0, password: $1) }

        let credentialsEmpty = credentials
            .map{ credentials in
                credentials.email.characters.count > 0 && credentials.password.characters.count > 0
            }
            .distinctUntilChanged()

        self.loginEnabled = Driver
            .combineLatest(credentialsEmpty, self.isWorking){ !($0 || $1) }
            .distinctUntilChanged()
    }

}

And here is my ViewController:

class LoginViewController: NSViewController {

    var screenManager: ScreenManager!

    @IBOutlet weak var emailField: NSTextField!
    @IBOutlet weak var passwordField: NSSecureTextField!
    @IBOutlet weak var loginButton: NSButton!
    @IBOutlet weak var loginSpinner: NSProgressIndicator!
    @IBOutlet weak var errorLabel: NSTextField!

    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        let vm = LoginVM(
            input: (
                email: self.emailField.rx_text.asDriver(),
                password: self.passwordField.rx_text.asDriver(),
                loginRequests: self.loginButton.rx_tap.asDriver()
            ),
            dependency: RoundedClient.sharedInstance
        )

        vm.loginEnabled
            .driveNext{ [weak self] enabled in
                self?.loginButton.enabled = enabled
                self?.loginButton.alphaValue = enabled ? 1.0 : 0.5
            }.addDisposableTo(self.disposeBag)

        vm.isWorking
            .drive(self.loginSpinner.ex_animating)
            .addDisposableTo(self.disposeBag)
    }

}

Here is an example when I attach ".debug()" to credentialsEmpty driver on LoginVM:

2016-04-17 16:32:36.730: LoginViewController.swift:38 (init(input:dependency:)) -> subscribed
2016-04-17 16:32:36.731: LoginViewController.swift:38 (init(input:dependency:)) -> Event Next(false)
2016-04-17 16:32:39.081: LoginViewController.swift:38 (init(input:dependency:)) -> Event Next(true)
2016-04-17 16:32:39.081: LoginViewController.swift:38 (init(input:dependency:)) -> disposed

It is getting disposed as soon as value is emitted after initial one.

4

2 に答える 2

1

LoginVM インスタンス変数をクラス メンバー フィールドに移動します。

let vm = LoginVM( ...

上記の 'vm' インスタンスは viewDidLoad() 関数に局所性があります

于 2016-05-23T08:13:32.927 に答える