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 实例变量移动到类成员字段。

让 vm = LoginVM( ...

上面的“vm”实例在 viewDidLoad() 函数中具有局部性

于 2016-05-23T08:13:32.927 回答
0

我遇到了这个问题,因为我写了

let disposeBag = DisposeBag()

方法里面viewDidLoad。一旦方法完成,这有效地使其超出了范围。

于 2017-08-04T15:52:24.170 回答