【问题标题】:How to have only 1 completion handler for 2 Alamofire request in the same function如何在同一函数中为 2 个 Alamofire 请求只有 1 个完成处理程序
【发布时间】:2017-12-23 04:42:03
【问题描述】:

我有一个函数,里面有 2 个 Alamofire 请求和一个完成处理程序。一旦我的两个请求都完成了从服务器下载数据,我想重新加载我的 collectionView。我在函数中有一个完成处理程序,但它被调用了两次,这导致我的 collectionView 重新加载了两次,我只想重新加载一次。有没有办法让我这样做?非常感谢!

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

这是我在 ViewDidLoad 中调用函数的方式

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

【问题讨论】:

    标签: ios swift alamofire completionhandler


    【解决方案1】:

    更好的解决方案

    使用DispatchGroup 这是示例

       let dispatchGroup = DispatchGroup()
    
        dispatchGroup.enter()
    
    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)
            }
          dispatchGroup.leave()
        }
    
     dispatchGroup.enter()
    
        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)
            }
           dispatchGroup.leave()
        }
    

    这是魔法线

    dispatchGroup.notify(queue: .main) {
        print("Both functions complete ?")
    }
    

    每次对 enter() 的调用必须在稍后与对 leave() 的调用相匹配,之后该组将调用提供给 notify() 的闭包。

    【讨论】:

    • @kevinvu 乐于助人:)
    【解决方案2】:

    如下所示更新您的getFeedVideos 方法:

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

    正如我在您的代码中看到的,您在两个 API 调用中都调用了 completion(true),这就是它多次重新加载的原因。在我的代码中,我已将您的第一个 API 调用中的 completion(true) 替换为另一个 API 调用,因此一旦您的两个 API 调用完成,您的 completion(true) 就会调用。

    希望这会有所帮助。

    注意:

    没有在 Xcode 上检查此代码,所以如果您对此代码有任何问题,请告诉我。

    【讨论】:

    • 有效!我只需要将 self 放在第二个请求调用中以供参考。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 2015-07-03
    • 2022-01-21
    • 2017-02-16
    相关资源
    最近更新 更多