如何在同一函数中为 2 个 Alamofire 请求只有 1 个完成处理程序

Posted

技术标签:

【中文标题】如何在同一函数中为 2 个 Alamofire 请求只有 1 个完成处理程序【英文标题】:How to have only 1 completion handler for 2 Alamofire request in the same function 【发布时间】: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()
            
        
    

【问题讨论】:

【参考方案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 放在第二个请求调用中以供参考。非常感谢!

以上是关于如何在同一函数中为 2 个 Alamofire 请求只有 1 个完成处理程序的主要内容,如果未能解决你的问题,请参考以下文章

如何在 laravel 的一个函数中为同一路线返回多个视图

Swift 2 - 如何从 Alamofire.responseJSON 获取数据

如何在javascript中为事件发送2个参数

如何在循环symfony2中为同一实体添加重复的表单

如何在 iOS 中为两个 UIView 翻转设置动画?

将数据从一个函数传递到同一个 Angular 组件中的另一个函数