1

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)
    }
}
9
  • It looks good provide more details what you want to achieve & is there any tableview or collection structure you are using ? Commented May 6, 2016 at 5:38
  • I want success(relatedVideos) to be called when all getVideosForShow sucessblocks have been completed. Currently it will call the success(relatedVideos) block immediately. Yes the results will be used to populate a collection view later on, however that is unrelated to this issue. Commented May 6, 2016 at 5:46
  • then you have to use a completionhandler for getNextVideoRecommendations method and call success(relatedvideos) from where you are call getNextVideoRecommendations Commented May 6, 2016 at 5:48
  • Or a workaround will be to use for loop like for (index, show) in relatedShows { & check for condition if index == relatedShows.count-1 at the last of for loop to call success(relatedVideos) Commented May 6, 2016 at 5:50
  • The completionhandler is success(). See method signature. The problem is, how do you know when all the getVideosForShow completionHandlers (success block) has been called? Commented May 6, 2016 at 5:53

1 Answer 1

4

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)
        }
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Perfect! Thanks so much. Just for future reference, is it possible to do this using NSOperationQueue as well?
Yes, you can use dependencies between operations to make your final operation execute only once all the others have finished.
Would you be able to send me a code snippet for that if you have a chance please? I tried it myself using dependencies but I'm pretty sure did it wrong
If you're having trouble and can show what you've tried, you might want to ask a different question. The basics are probably NSBlockOperation to execute the final success callback, and using addDependency before you put it in an operation queue.
I tried creating block operations for the "Finished all operations" and then created block operations for inside the success block of show.getVideosForShow. But It doesn't quite work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.