2017-09-25 102 views
1

我从FatSecret API获取数据。简而言之,我有几个食物ID需要从中获取数据,迭代它们以将卡路里加在一起。每个人都必须是一个单独的电话。由于这些不会在主线程中运行,因此确定它们何时完成的最佳方法是什么?目前,我使用每次调用完成时迭代一次的变量来追踪它,但我觉得可能有更好的方法。迭代APi结果的最佳方式是什么,并知道何时完成?

for thisFoodId in foodIds { 

    let endpointURL = <URL WITH FOODID> 
    guard let url = URL(string: endpointURL) else { 
     return 
    } 
    let urlRequest = URLRequest(url: url) 
    let config = URLSessionConfiguration.default 
    let session = URLSession(configuration: config) 
    let task = session.dataTask(with: urlRequest, completionHandler: { 
     (data, response, error) in 

     guard error == nil else { 
      return 
     } 
     guard let responseData = data else { 
      return 
     } 

     do { 

      guard let thisData = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: AnyObject] else { 
       return 
      } 

      let calories = thisData["calories"] 
      self.totalCalories += calories 
      tracker += 1 
      if tracker == foodIds.count { 
       // RUN COMPLETION CODE 
      } 
     } 
     } 

回答

2

您可以使用DispatchGroups。当您的所有请求都完成时,它会触发一个异步回调模块。

DispatchGroup:

DispatchGroup允许工作的总同步。您可以使用 来提交多个不同的工作项目,并跟踪它们何时全部完成,即使它们可能运行在不同的队列中。当所有 指定任务完成时,如果无法取得进展,则此行为可能会有所帮助。

在你的代码,这将是这样的:

// ... 

// Create the DispatchGroup: 

let dispatchGroup = DispatchGroup() 

for thisFoodId in foodIds { 

    // Enter the DispatchGroup: 

    dispatchGroup.enter() 

    // ... 

    let task = session.dataTask(with: urlRequest, completionHandler: { 
     (data, response, error) in 

     // ... 

     do { 

      // ... 

      if tracker == foodIds.count { 

       // Leave the DispatchGroup 

       dispatchGroup.leave() 
      } 
     } 

    }) 

    // When all your tasks have completed, notify your DispatchGroup to run your work item: 

    dispatchGroup.notify(queue: DispatchQueue.main, execute: { 

     // All your async requests are finished here, do whatever you want :) 

    }) 

} 
+1

这正是我一直在寻找。谢谢! – user1328035

+0

不客气!祝你的项目好运:) – Alex

相关问题