kevin vu kevin vu - 8 months ago 79
iOS Question

How to have only 1 completion handler for 2 Alamofire request in the same function

I have a function with 2 Alamofire requests inside with a completion handler. I want to reload my collectionView once I have both requests completed downloading data from server. I have a completion handler in the function but it gets called twice which causes my collectionView reload twice and I would love to reload only one time. Is there a way that I can do so? Thank you so much!

func getFeedVideos(completion: @escaping (_ completedDownloadVideo: Bool) -> ()){

Alamofire.request(youTubeUrl, method: .get, parameters: ["part":"snippet","maxResults": "20","nextPageToken" : "pageToken", "playlistId": playListId, "key": googleAPIKey], encoding: URLEncoding.default, headers: nil).responseJSON { (response) in
guard let data = response.data else {return}
do {
let json = try JSONDecoder().decode(serverData.self, from: data)
self.dataFromAPI = json.items
completion(true)
} catch let jsonErr{
print(jsonErr)
}
}

Alamofire.request(youTubeChannelUrl, method: .get, parameters: ["part":"snippet", "key": googleAPIKey, "id": youTubeChannelId], encoding: URLEncoding.default, headers: nil).responseJSON { (response) in
guard let data = response.data else {return}
do {
let json = try JSONDecoder().decode(channelInfo.self, from: data)
self.channelData = json.items
completion(true)
} catch let jsonErr{
print(jsonErr)
}
}
}


and here is how I called the function in ViewDidLoad

override func viewDidLoad() {
super.viewDidLoad()
getFeedVideos { (complete) in
if complete{
DispatchQueue.main.async {
self.collectionView?.reloadData()
}
}
}
}

Answer Source

Update your getFeedVideos method as shown below:

func getFeedVideos(completion: @escaping (_ completedDownloadVideo: Bool) -> ()){

    Alamofire.request(youTubeUrl, method: .get, parameters: ["part":"snippet","maxResults": "20","nextPageToken" : "pageToken", "playlistId": playListId, "key": googleAPIKey], encoding: URLEncoding.default, headers: nil).responseJSON { (response) in
        guard let data = response.data else {return}
        do {
            let json = try JSONDecoder().decode(serverData.self, from: data)
            self.dataFromAPI = json.items

            Alamofire.request(youTubeChannelUrl, method: .get, parameters: ["part":"snippet", "key": googleAPIKey, "id": youTubeChannelId], encoding: URLEncoding.default, headers: nil).responseJSON { (response) in
                guard let data = response.data else {return}
                do {
                    let json = try JSONDecoder().decode(channelInfo.self, from: data)
                    self.channelData = json.items
                    completion(true)
                } catch let jsonErr{
                    print(jsonErr)
                }
            }
        } catch let jsonErr{
            print(jsonErr)
        }
    }
}

As I am seeing in your code you are calling completion(true) in both API calls thats why its reloading multiple times. In my code I have replaced completion(true) from your first API call with another API call so Once your both API call with complete your completion(true) will call.

Hope this will help.

Note:

Didn't checked this code on Xcode so let me know if you got any issue with this code.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download