我有一个函数,我需要获取2个数组的差异并使用完成来返回字典形式的差异。它需要网络调用才能从TVDB api创建一个对象。我尝试使用.enter()和.leave()实现dispatchGroups,一切似乎都以正确的顺序工作(使用断点检查),直到最后一次迭代它在“groupDispatch.leave()”的行上崩溃,没有错误消息在控制台中。
这是有问题的功能:
func showsToWatch(idArray: [Int], completion:@escaping(_ dict: [Int:[Int]])->Void){
var toWatch:[Int:[Int]] = [:]
let groupDispatch = DispatchGroup()
for id in idArray {
groupDispatch.enter()
guard let watchedId = SeriesController.sharedController.watchedDict[id] else {return}
NetworkController.getEpisodes(id) { (episodes, error) in
if let episodes = episodes {
let episodesId = episodes.map({$0.id})
let difference = episodesId.filter { !watchedId.contains($0) }
toWatch[id] = difference
}
groupDispatch.leave()
}
}
groupDispatch.notify(queue: DispatchQueue.main, execute: { () -> Void in
completion(toWatch)
})
}
这是NetworkController.getEpisodes函数:
static func getEpisodes(_ id: Int, completion:@escaping (_ episode: [Episode]?, _ error: NSError?)->Void) {
NetworkController.getPageCount(id) { (pageCount) in
var allEpisodes = [Episode]()
for i in 1...pageCount {
let idString = String(id)
let searchUrl = baseUrl + "series/\(idString)/episodes?page=\(i)"
let searchParam = searchUrl
let myUrl = URL(string: searchParam)
var request = URLRequest(url:myUrl!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Accept")
let headerString = "Bearer " + myToken
request.addValue(headerString, forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
if error != nil {
print("error=\(error)")
completion(nil, error as NSError?)
return
}
do {
if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
if let dataDict = convertedJsonIntoDict as? [String:AnyObject] {
if let dataArray = dataDict["data"] as? [[String:AnyObject]]{
for episodeDict in dataArray {
let episode = Episode(dict: episodeDict)
//print("S\(episode.airedSeason)E\(episode.airedEpisodeNumber)")
if episode.absoluteNumber < 0 {
if episode.airedSeason > 0 && episode.airedEpisodeNumber > 0 {
allEpisodes.append(episode)
}
} else {
allEpisodes.append(episode)
}
}
}
}
}
completion(allEpisodes, nil)
} catch let error as NSError {
print(error.localizedDescription)
completion(nil, error as NSError?)
}
}); task.resume()
}
}
}
我尝试将groupDispatch.leave()放在函数/ for循环中的不同位置但是它没有以正确的顺序完成(编辑:它在将变量“difference”数组设置为之前完成完成“toWatch”字典变量中的正确键)。我对.leave()的工作方式感到有点困惑。
谢谢!