Well i am pretty much new to reactive programming. problem is, I have a function(A) which returns an object , now I have another function(B) which subscribes returning object from function A and I make function B also as returning an other object in that subscribe, now this whole return this is not work. I have no idea why is happening. Any help would be appreciated. Thanks Function A
func getClassById(classId: Int) -> Observable<Bool> {
return Observable.create{[weak self] observer -> Disposable in Alamofire.request("URL", method:.get, parameters: nil, encoding: JSONEncoding.default, headers: self!.getRequestHeader())
.validate()
.responseJSON{ response in
switch response.result {
do {
let assingnedClass = try JSONDecoder().decode(AssignedClassModel.self, from: data)
observer.onNext(true)
} catch {
observer.onError(error)
}
case .failure(let error):
observer.onError(error)
}
}
return Disposables.create()
}
}
Function B
func getAssignedClassData(classId: Int) -> Observable<[StudentModel]> {
return Observable.create{[weak self] observer -> Disposable in // from here code is not going further.
APIService.singelton
.getClassById(classId: classId)
.asObservable()
.subscribe(onNext: { [weak self] assingnedClass in
let studentsData = Array(Database.singleton.fetchStudents(byCLassId: classId))
print(studentsData)
observer.onNext(studentsData)
}, onError: { error in
print(error)
}).disposed(by: self!.disposeBag)
return Disposables.create()
}
}
Function B2
func getAssignedClassData(classId: Int) -> Observable<[StudentModel]> {
return APIService.singelton
.getClassById(classId: classId)
.do(onError: { error in
print(error)
})
.map({ [weak self] assingnedClass in
return Array(Database.singleton.fetchStudents(byCLassId: classId))
// this code will not be triggered as it is after return.
let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "tabBarVC") as? TabBarViewController
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.default)
transition.type = CATransitionType.fade
self?.navigationController?.view.layer.add(transition, forKey: nil)
self?.navigationController?.pushViewController(vc!, animated: true)
})
}
There is no Observable creation needed in Function B. If you want to transform one observable to another you can use map
operator.
There is an error handling trouble in Function B. Error will be caught, but Observable will never be completed. In my example I used just side effect for printing error, so error will be propagated and map
will not run. There are some strategies for error handling in RxSwift.
Function B doesn't need asObservable
.
The result of Function A (assingnedClass
) is not used. Probably the real code was simplified.
There is no observer.onCompleted()
after observer.onNext()
in Function A. Your observable will not be completed and disposed at time.
Here is my example:
class StudentService {
...
func getAssignedClassData(classId: Int) -> Observable<[StudentModel]> {
return APIService.singelton
.getClassById(classId: classId)
.do(onError: { error in
print(error)
})
.map { _ in Array(Database.singelton.fetchStudents(byCLassId: classId)) }
}
}
class SomeController: UIViewController {
...
func fetchStudentsAndPushViewController() {
studentService
.getAssignedClassData(classId: classId)
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] _ in
let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "tabBarVC") as? TabBarViewController
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.default)
transition.type = CATransitionType.fade
self?.navigationController?.view.layer.add(transition, forKey: nil)
self?.navigationController?.pushViewController(vc!, animated: true)
})
.disposed(by: self!.disposeBag)
}
}
BTW. You can try RxAlamofire for you APIService
so you won't need to wrap the request into Observable by yourself.