Smashkon Smashkon - 6 months ago 7
Swift Question

Callbacks with array

I am trying to setup the following method to perform the success block once all the show.getVideosForShow() success blocks have been performed and all videos appended. Note: show.getVideosForShow() is asynchronous and could take a few seconds to get a result.
Could someone please provide some assistance?

private func getNextVideoRecommendations(success: ([Video]) -> ()) {
var relatedVideos = [Video]()
if let relatedShows = self.videoCurrentlyPlaying?.show?.getShowsWithSameGenre(fetchLimit: 3) {
for show in relatedShows {
show.getVideosForShow(tvSeason: nil, longForm: true, sortType: VideoSort.Latest, success: { (videos: [Video]) in
print("Found Related Show: \(show.title)")
if videos.count > 0 {
relatedVideos.append(videos[0])
}
})
}
print("Finished all operations")
success(relatedVideos)
}
}

Answer

This is a good use case for dispatch groups, which allow you to submit another block once all your operations have finished:

private func getNextVideoRecommendations(success: ([Video]) -> ()) {
    var relatedVideos = [Video]()
    if let relatedShows = self.videoCurrentlyPlaying?.show?.getShowsWithSameGenre(fetchLimit: 3) {
        let group = dispatch_group_create()
        for show in relatedShows {
            dispatch_group_enter(group)  // start tracking one unit of work
            show.getVideosForShow(tvSeason: nil, longForm: true, sortType: VideoSort.Latest, success: { (videos: [Video]) in
                print("Found Related Show: \(show.title)")
                if videos.count > 0 {
                    relatedVideos.append(videos[0])
                }
                dispatch_group_leave(group)  // finish one unit of work
            })
        }
        dispatch_group_notify(group, dispatch_get_main_queue()) {  // and when done...
            print("Finished all operations")
            success(relatedVideos)
        }
    }
}
Comments