简体   繁体   中英

RxSwift + MVVM + Coordinator Pattern, How to wait for coordinator result sequentially?

Scenario:

I have base coordinator which basically like so:

class Coordinator<Result> {
   // some coordinator class codes

   func coordinate(to: Coordinator<T>) -> Observable<T> {
       return coordinator.start()
   }

   func start() -> Observable<Result> {
      // return result
   }
} 

and TestCoodinator1, TestCoordinator2, TestCoodinator3 like so:

enum Status {
    case .success(data: NSData?)
    case .cancelled(error: NSError?)
    case .failed(data: NSData?)
}

class TestCoordinator1: Coordinator<Status> {
     // Init pass UINavigationController as rootViewController

     let testVC1 = TestViewController1()
     let testVM1 = TestViewModel1()
     testVC1.viewModel = testVM1         

     return testVM1.status // returns Observable<Status>
         .do(onNext: { [unowned self] _ in self?.rootViewController.popViewController(animated: true)
} 

and I have main coordinator which basically like so:

class MainCoordinator: Coordinator<Void> {

    override func start() -> Observable<Void> {
        let mainVC = MainVC()
        let mainVM = MainVM()
        mainVC.viewModel = mainVM

        let testCoordinator1 = TestCoordinator1(in: rootViewController)
        let viewModel1 = ViewModel1()
        testCoordinator1.viewModel = viewModel1

        let testCoordinator2 = TestCoordinator2(in: rootViewController)
        let viewModel2 = ViewModel2()
        testCoordinator2.viewModel = viewModel2

        let testCoordinator3 = TestCoordinator3(in: rootViewController)
        let viewModel3 = ViewModel3()
        testCoordinator3.viewModel = viewModel3

        // viewModel.tests returns Observable that has three types of tests randomly generated
        // Observable.of("Test1", "Test2", "Test3")
        mainVM.tests ????

        return Observable.never()
    }
}

The problem:

How do I create observable that coordinates to test1 and wait test1 complete first, then do some processing on the result, then and only then test2 run, process some result, and then test3 run.

If I do it like so:

mainVM.tests
   .flatMap { test in 
       switch(test) {
           case "Test1":
                 return self.coordinate(to: testCoordinator1)
           case "Test2":
                 return self.coordinate(to: testCoordinator2)
           case "Test3":
                 return self.coordinate(to: testCoordinator3)
       }
   }
   .subscribe(onNext: { status in 
      self.processStatus(status)
   })

all three coordinators run at the same time

If I understand you correctly, you can achieve that by chaining observables :

mainVM.tests
    .flatMapLatest { test -> Observable<...> in
        // do some things
        return self.coordinate(to: testCoordinator1)
    }
    .flatMapLatest { _ -> Observable<...> in
        // handle first coordinator
        return self.coordinate(to: testCoordinator2)
    }
    .flatMapLatest { _ -> Observable<...> in
        // handle second coordinator
        return self.coordinate(to: testCoordinator3)
    }
    .flatMapLatest { _ -> Observable<...> in
        // handle third coordinator
    }
    .subscribe(onNext: { status in
        self.processStatus(status)
    })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM