Search code examples
arraysswiftasynchronousalamofirefor-in-loop

Call a function after making multiple requests only


I'm making a HTTP request with Alamofire for each item in an array, using a for-in loop. I want to call a function after I get all the responses:

for product in products {
    let requestURL = "http://api.com/" + product
    let parameters = ["apiKey" : "myApiKey"]
    Alamofire.request(.GET, requestURL, parameters: parameters)                  
        .responseJSON { response in
             // do stuff here
        }
}

In order to call a function when it's all done, I figured I could check if product is the last element of the array, and then call the function if that's the case (since requests are asynchronous). How can I do it?


Solution

  • You should use GCD to get notified when all the requests finish. Use dispatch_group_create and dispatch_group_notify. For implementation details check out this thread.

    Sample code from the linked thread:

    func downloadAllData(allDataDownloadedCompletionHandler:()->Void) {
        let dispatchGroup: dispatch_group_t = dispatch_group_create()
        let types = ["one", "two", "three"]  // there are actually about 10 requests called, but to make it simple I set it to 3
        for type in types {
            // enter group and run request
            dispatch_group_enter(dispatchGroup)
            self.downloadDataForType(type, group: dispatchGroup)
        }
    
        dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), {
            allDataDownloadedCompletionHandler()
        });
    }
    
    func downloadDataForType(type:String, group: dispatch_group_t) {
        Alamofire.request(Router.TypeData(type: type)).response({ (request, response, xmlResponse, error) -> Void in
            // request finished
            println("Data for type \(type) downloaded")
    
            // let's parse response in different queue, because we don't want to hold main UI queue 
            var db_queue = dispatch_queue_create("db_queue", nil)
                dispatch_async(db_queue, {
                if response?.statusCode == 200 {
                   saveToDatabase(xmlResponse)
               }
    
                // leave group
                dispatch_group_leave(group)
            })
        })
    }