RxSwift - нажатие кнопки с использованием темы публикации - PullRequest
0 голосов
/ 07 июня 2019

Итак, у меня внутри кнопки ViewController есть кнопка, которая подключена к ViewModel, и, когда бы она ни была нажата, в моем координаторе я перехожу на другой экран.Код выглядит так:

VC

btnShowShopsMap.rx.tap
            .bind(to: viewModel.selectShowMap)

VM

let selectShowMap: AnyObserver<Void>
    let showShopMap: Observable<Void>
//Inside init
 let _selectShowMap = PublishSubject<Void>()
        selectShowMap = _selectShowMap.asObserver()
        showShopMap = _selectShowMap.asObservable()

Coordinator

viewModel.showShopMap
            .subscribe(onNext: { _ in self.showShopMap()})
            .disposed(by: userShopVC.disposeBag)

ЭтоМожно ли провести рефакторинг кода выше?вместо использования PublishSubject есть ли другой способ сделать то, что я делаю, используя PublishSubject

Мой VC, VM & Coordinator Flow

Coordinator

func showLoginScreen(logout: Bool = false) {

    guard let viewController = LoginViewController.instantiate(storyboard: .main) else { return }

    viewController.viewModelFactory = { inputs in
        let viewModel = LoginViewModel(inputs: inputs)
        viewModel.showHome
            .subscribe(onNext: {  isLogged in
                if isLogged {
                    self.showHomeScreen()
                }
            })
            .disposed(by: viewController.disposeBag)

        inputs.showOnboarding
            .subscribe(onNext: { _ in
                self.showOnboardingScreen()
            })
            .disposed(by: viewController.disposeBag)
        return viewModel
    }
navController.pushViewController(viewController, animated: true)

VC

var viewModelFactory: (LoginViewModel.UIInputs) -> LoginViewModel = { _ in fatalError("factory not set")}

let inputs = LoginViewModel.UIInputs(userNumber: txtUserNumber.rx.text.orEmpty.asDriver(),
                                             password: txtPassword.rx.text.orEmpty.asDriver(),
                                             loginTapped: btnLogin.rx.tap.asSignal(),
                                             userNumberLostFocus: txtUserNumber.rx.controlEvent(.editingDidEnd).asSignal(),
                                             passwordLostFocus: txtPassword.rx.controlEvent(.editingDidEnd).asSignal(),
                                             indicator: indicator,
                                             showOnboarding: btnShowOnboarding.rx.tap.asObservable())

VM

struct  UIInputs {
    let userNumber: Driver<String>
    let password: Driver<String>
    let loginTapped: Signal<Void>
    let userNumberLostFocus: Signal<Void>
    let passwordLostFocus: Signal<Void>
    let indicator: ActivityIndicator
    let showOnboarding: Observable<Void>
}
 init(inputs: UIInputs) {}

Ответы [ 2 ]

1 голос
/ 07 июня 2019

Предполагая, что контроллер представления владеет и создает экземпляр модели представления, вы можете передать событие управления отводом в качестве наблюдаемого инициализатору модели представления, который затем предоставляет его в качестве наблюдаемого для координатора, на который можно подписаться:

// VC:
let viewModel = ViewModel(..., showShopMap: btnShowShopMap.rx.tap.asObservable())

// VM:
let showShopMap: Observable<Void>

init(..., showShopMap: Observable<Void>) {
    self.showShopMap = showShopMap
}

Я стараюсь не использовать предметы всякий раз, когда это возможно, и вместо этого просто выставляю преобразованные наблюдаемые, которые были переданы.

0 голосов
/ 08 июня 2019

Я нашел очень простой и простой способ решить мою проблему и избегать использования Subject, так как не было логики, связанной с моей кнопкой в ​​ВМ, мне не нужно передавать кнопку «Нажатие» моей ВМ также с помощью Observable или используя Subject. Вместо этого я напрямую получил доступ к своей кнопке в координаторе, как это:

viewController.btnShowOnboarding.rx.tap
      .subscribe(onNext: { _ in
         self.showOnboardingScreen()
      })
     .disposed(by: viewController.disposeBag)
...