Reputation: 207
Hello I have been trying alot and looking around on SO, but I cant find a good solution to my problem.
The problem is that i do 2 requests within one function and the first one finishes, then it does updateUI function on the main thread instead of waiting for the second download to finish.
I know that i am doing something wrong but in my mind the two requests work on different threads and that is why updateUI only will trigger after first download is complete.
Is it possible to use dispatchqueue? I dont know how completionhandlers work either sadly..
I couldnt see what i have to use from their github page either, im quite new at Swift.
Please do not set this as duplicate. would really appreciate it
func getMovieData(){
self.posterLoading.startAnimating()
//Set up URL
let testCall: String = "https://api.themoviedb.org/3/discover/movie?api_key=935f5ddeed3fb57e&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1&with_genres=12"
Alamofire.request(testCall).responseJSON { response in
//print(response.request) // original URL request
//print(response.response) // HTTP URL response
//print(response.data) // server data
//print(response.result) // result of response serialization
if let json = response.result.value as? Dictionary<String,AnyObject> {
if let movies = json["results"] as? [AnyObject]{
for movie in movies{
let movieObject: Movie = Movie()
let title = movie["title"] as! String
let releaseDate = movie["release_date"] as! String
let posterPath = movie["poster_path"] as! String
let overView = movie["overview"] as! String
let movieId = movie["id"] as! Int
let genre_ids = movie["genre_ids"] as! [AnyObject]
movieObject.title = title
movieObject.movieRelease = releaseDate
movieObject.posterPath = posterPath
movieObject.overView = overView
movieObject.movieId = movieId
for genre in genre_ids{//Genre ids, fix this
movieObject.movieGenre.append(genre as! Int)
}
Alamofire.request("http://image.tmdb.org/t/p/w1920" + posterPath).responseImage {
response in
debugPrint(response)
//print(response.request)
//print(response.response)
//debugPrint(response.result)
if var image = response.result.value {
image = UIImage(data: response.data!)!
movieObject.poster = image
}
}
self.movieArray.append(movieObject)
print("movie added")
}//End of for each movie
DispatchQueue.main.async(){
print("is ready for UI")
self.updateUI()
}
}
}
}//End of Json request
}//End of getmoviedata
func updateUI(){
uiMovieTitle.text = movieArray[movieIndex].title
uiMoviePoster.image = movieArray[movieIndex].poster
}
Upvotes: 0
Views: 1533
Reputation: 381
Your function should look like this.
func getMovieData(completionHandler: @escaping (_ returnedData: Dictionary<String,AnyObject>)-> Void ) {
Alamofire.request(testCall).response { response in
if let JSON = response.result.value {
completionHandler(JSON)
}
}
}
And your function call look like
getMovieData(completionHandler: {(returnedData)-> Void in
//Do whatever you want with your returnedData JSON data.
//when you finish working on data you can update UI
updateUI()
})
You don't have to do your data operations in your function call btw.You can do your stuff in your function and call the completionHandler() end of it. Then you can update your ui only at function call.
Upvotes: 1
Reputation: 2918
Just make your getMovieData
func with a completion block.
func getMovieData(finished: () -> Void) {
Alamofire.request(testCall).responseJSON { response in
// call me on success or failure
finished()
}
}
and then you can call your update UI in the completion block of the func, where you calling it the second time getMovieData()
Upvotes: 1