0
votes
class MainViewController: UIViewController {
    let button = UIButton()
    let mainViewModel = MainViewModel()
    let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(button)
        button.frame = CGRect(x: 50, y: 50, width: 100, height: 30)
        
        bind()
    }
    
    func bind() {
        button.rx.tap
            .bind(to: mainViewModel.doAction)
            .disposed(by: disposeBag)
        
        mainViewModel.somethingDoneObservable
            .observeOn(MainScheduler.instance)
            .flatMapLatest { [weak self] value -> Observable<String> in
                print(value)
                
                let vc = Work1ViewController()
                
                self?.present(vc, animated: true, completion: nil)
                
                return vc.work1ViewModel.work1DoneObservable
            }
            .flatMapLatest { [weak self] value -> Observable<String> in
                print(value)

                let vc = Work2ViewController()

                self?.present(vc, animated: true, completion: nil)

                return vc.work2ViewModel.work2DoneObservable
            }
            .subscribe(onNext: { newValue in
                // do something
                // all done
                print(newValue)
            })
            .disposed(by: disposeBag)
    }
}

class MainViewModel {
    let doAction = PublishSubject<Void>()
    let somethingDoneObservable = PublishSubject<String>()
    let disposeBag = DisposeBag()
    
    init() {
        doAction
            .subscribe(onNext: {
                // do something
                let when = DispatchTime.now() + DispatchTimeInterval.milliseconds(5000)
                
                DispatchQueue.main.asyncAfter(deadline: when) {
                    self.somethingDoneObservable.onNext("Something Done!!")
                }
            })
            .disposed(by: disposeBag)
    }
}

// ----------------------------------------------------------------------

class Work1ViewController: UIViewController {
    let button = UIButton()
    let work1ViewModel = Work1ViewModel()
    let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(button)
        button.frame = CGRect(x: 50, y: 50, width: 100, height: 30)
        
        bind()
    }
    
    func bind() {
        button.rx.tap
            .bind(to: work1ViewModel.doAction)
            .disposed(by: disposeBag)

        work1ViewModel.work1DoneObservable
            .subscribe(onNext: { [weak self] _ in
                self?.dismiss(animated: false, completion: nil)
            })
            .disposed(by: disposeBag)
    }
}

class Work1ViewModel {
    let doAction = PublishSubject<Void>()
    let work1DoneObservable = PublishSubject<String>()
    let disposeBag = DisposeBag()
    
    init() {
        doAction
            .subscribe(onNext: {
                // do work1
                let when = DispatchTime.now() + DispatchTimeInterval.milliseconds(5000)
                
                DispatchQueue.main.asyncAfter(deadline: when) {
                    self.work1DoneObservable.onNext("Work1 Done!!")
                }
            })
            .disposed(by: disposeBag)
    }
}

(Work1, Work2ViewController can be dismissed without doAction event.)

as you see, I want to connet several work steps.(work1 -> work2 -> mainVc)

in this case, I used flatMapLatest.

  1. is it correct way? if not, is there common way or other elegant way?

  2. if it is correct, is there any problem?(memory leak or ..)

  3. if I tap MainViewController'button later, is it ok?