Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RXSwift Not subscribing on Main Thread

I am trying to make several API calls and populate a Realm Database. Everything works fine. However when I try to run performSegue() on subscribe() method an exception is raised, informing that I can't do this on a background thread, which is perfectly reasonable.

But since I am subscribing to MainScheduler.instance shouldn't the subscribe() method run on UI Thread?

Single.zip(APIClient.shared.getSchools(), APIClient.shared.getPointsOfInterest())
        .observeOn(SerialDispatchQueueScheduler(qos: .background))
        .flatMap { zip in return Single.zip(SchoolDao.shared.insertSchools(schoolsJson: zip.0), PointOfInterestDao.shared.insertPointsOfInterest(poisJson: zip.1))}
        .flatMap{ _ in Single.zip(SchoolDao.shared.countSchools(), PointOfInterestDao.shared.countPointsOfInterest())}
        .subscribeOn(MainScheduler.instance)
        .subscribe(onSuccess: { tableCounts in
            let (schoolsCount, poisCount) = tableCounts
            if(schoolsCount != 0 && poisCount != 0){
                print(Thread.isMainThread) //Prints False
                self.performSegue(withIdentifier: "splashToLogin", sender: nil)
            }
        }, onError: {
            error in return
        }).disposed(by: disposeBag)

Am I making a wrong assumption on how does RXSwift works?

Edit: If I add this line .observeOn(MainScheduler.instance) after .subscribeOn(MainScheduler.instance) the subscribe method runs on Main thread. Is this correct behavior? What is .subscribeOn(MainScheduler.instance) even doing?

like image 778
Exprove Avatar asked Oct 12 '19 16:10

Exprove


1 Answers

Your edit explains all. Your initial assumption on what subscribeOn and observeOn were backwards.

The subscribeOn operator refers to how the very first observable in the chain subscribes to the ultimate source of events (and likely doesn't do what you think it does in any case. Your two network calls likely set up their own background thread to emit values on regardless of how they are subscribed to.)

The observeOn operator refers to the scheduler that will be emitting elements to the observer (which is the block(s) of code that are passed to the subscribe operator.)

Here is a great article explaining the whole thing: http://rx-marin.com/post/observeon-vs-subscribeon/

like image 140
Daniel T. Avatar answered Oct 01 '22 01:10

Daniel T.