Search code examples
iosswiftalamofirecompletionhandler

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()
            }
        }
    }
}

Solution

  • 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.