Reputation: 17
When I use loadMovies function I get desired movies only after the ViewController has called function and disposed it, this function is inside API
func loadMovies() -> Observable<[Movie]> {
let obsMovies = self.APICall(genrePath: Movies.action, structType: Movie.self)
return Observable.create{ observer -> Disposable in
obsMovies.subscribe(
onNext: { element in
observer.onNext(element)
print(element)
}
)
observer.onCompleted()
return Disposables.create()
}
}
In ViewController I call this function inside viewDidLoad
request.api.loadMovies()
.debug()
.subscribe(
onNext:{ data in
do {
print(data)
}
},
onError: { error in
print(error)
},
onCompleted: {
print("Completed")
},
onDisposed: {
print("Disposed")
}
)
.disposed(by: disposeBag)
and get this output
ViewController.swift:55 (viewDidLoad()) -> subscribed
ViewController.swift:55 (viewDidLoad()) -> Event completed
Completed
Disposed
ViewController.swift:55 (viewDidLoad()) -> isDisposed
[MovieTest.Movie(name: "Black Panther", year: "2018", rating: "83")]
[MovieTest.Movie(name: "AVENGERS: ENDGAME", year: "2019", rating: "90")]
[MovieTest.Movie(name: "MISSION: IMPOSSIBLE -- FALLOUT", year: "2018", rating: "88")]...
I want to how to wait for function to fetch movies before being disposed.I want to display everything in tableView. I'm beginner at RxSwift, I believe there is better way to achieve this but as of right now I have no idea. Thanks
Upvotes: 1
Views: 1930
Reputation: 33979
So there are a couple of problems to fix right away... obsMovies.subscribe()
returns a disposable that you are ignoring. Since the closure it's embedded in needs to return a disposable, how about just returning the one that subscribe created instead of making a new one:
func loadMovies() -> Observable<[Movie]> {
let obsMovies = self.APICall(genrePath: Movies.action, structType: Movie.self)
return Observable.create{ observer -> Disposable in
let disposable = obsMovies.subscribe(
onNext: { element in
observer.onNext(element)
print(element)
}
)
observer.onCompleted()
return disposable
}
}
Next, notice that APICall(genrePath:structType:)
returns an Observable<[Movie]>
so why not just return that rather than wrapping it in yet another Observable?
func loadMovies() -> Observable<[Movie]> {
return self.APICall(genrePath: Movies.action, structType: Movie.self)
}
Wow, now I kind of wonder why loadMovies()
exists at all... 🤔
So now that I have done the above, here's the output I see:
ViewController.swift:55 (viewDidLoad()) -> subscribed
ViewController.swift:55 (viewDidLoad()) -> Event next([MovieTest.Movie(name: "Black Panther", year: "2018", rating: "83"), MovieTest.Movie(name: "AVENGERS: ENDGAME", year: "2019", rating: "90"), MovieTest.Movie(name: "MISSION: IMPOSSIBLE -- FALLOUT", year: "2018", rating: "88")])
[MovieTest.Movie(name: "Black Panther", year: "2018", rating: "83"), MovieTest.Movie(name: "AVENGERS: ENDGAME", year: "2019", rating: "90"), MovieTest.Movie(name: "MISSION: IMPOSSIBLE -- FALLOUT", year: "2018", rating: "88")]
ViewController.swift:55 (viewDidLoad()) -> Event completed
Completed
Disposed
2021-04-11 20:05:08.356: Stuff.swift:55 (viewDidLoad()) -> isDisposed
Upvotes: 1