我正在尝试使用OMDb API编写权力的游戏情节纲要。我从服务器上获得的信息很好,但我很难将数据发送到我的UITableView。
这是调用闭包的函数和定义它的函数:
func getAllForSeason(season: Int) {
let uri = "\(baseURL)\(urlId)&season=\(season)"
var episodeList = [EpisodeModel]()
let url = URL(string: uri)
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print("Error retrieving information. No season found")
} else {
if let content = data {
do {
let seasonJSON = try JSONSerialization.jsonObject(with: content, options: .mutableContainers) as? [String: Any]
let episodesFound = seasonJSON?["Episodes"] as! [[String: String]]
for episodeJSON in episodesFound {
let number = Int(episodeJSON["Episode"] ?? "0") ?? 0
var episodeToAdd = EpisodeModel()
self.getTemporaryEpisode(season: season, number: number, completion: {(result:EpisodeModel) in
episodeToAdd = result
print(episodeToAdd.season)
})
print(episodeToAdd.season)
episodeList.append(episodeToAdd)
}
DispatchQueue.main.async {
self.delegate?.didGetSeason(episodes: episodeList)
}
} catch {
print ("Error retrieving information. No seasons found")
}
}
}
}
task.resume()
}
private func getTemporaryEpisode(season: Int, number: Int, completion: @escaping(_ response:EpisodeModel)->Void) {
let episode = EpisodeModel()
let uri = "\(baseURL)\(urlId)&season=\(season)&episode=\(number)"
let url = URL(string: uri)
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print("Error downloading episode information. Empty Episode returned")
} else {
if let content = data {
do {
let episodeJSON = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any]
episode.title = (episodeJSON?["Title"] as? String)?.description ?? ""
let dateString = (episodeJSON?["Released"] as? String)?.description ?? ""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy MMM dd"
episode.releaseDate = dateFormatter.date(from: dateString) ?? Date()
episode.rating = (episodeJSON?["Rated"] as? String)?.description ?? ""
episode.season = Int(episodeJSON?["Season"] as? String ?? "") ?? 0
episode.number = Int(episodeJSON?["Episode"] as? String ?? "") ?? 0
let runtimeString = (episodeJSON?["Runtime"] as? String)?.description ?? "0 min"
let spaceIndex = runtimeString.index(of: " ") ?? runtimeString.endIndex
let minuteString = runtimeString[runtimeString.startIndex..<spaceIndex]
episode.minutes = Int(minuteString) ?? 0
episode.director = (episodeJSON?["Director"] as? String)?.description ?? ""
episode.writer = (episodeJSON?["Writer"] as? String)?.description ?? ""
let actorsString = (episodeJSON?["Actors"] as? String)?.description ?? ""
episode.actors = actorsString.components(separatedBy: ", ")
episode.plot = (episodeJSON?["Plot"] as? String)?.description ?? ""
} catch {
print("Error downloading episode information. Empty or incomplete episode returned")
}
}
}
completion(episode)
}
task.resume()
}
我使用完全相同的方法对SW API(星球大战)做过类似的工作,然后就可以了。
用于测试的印刷语句应打印使用getTemporaryEpisode
但是,我发现当第一个print语句正确打印时(从闭包内),闭包之外的第二个打印0打印0(默认我设置以确保值被初始化),这意味着{{1} }不再包含结果。
例如:Winter Is Coming将在机箱内打印1,但在其中打印0。
它首先输出0,所以我确定它是一个线程问题,并且在第二个print语句被调用时没有发生完成。我只是不确定如何解决它。
编辑:我确实意识到我愚蠢地将我的调用放在循环内的主线程中,但修复它并没有解决这个问题。
答案 0 :(得分:0)
您的函数getTemporaryEpisode
是异步的,因此您通过一组空集来通知委托。
然后,您重新分配episodeToAdd
变量以引用正确设置的剧集,但这对episodeList
的内容没有任何影响。您可能希望等到填充episodeList
,直到您检索到正确的内容为止。您可以使用DispatchGroup
。
但是,如果您只是使用DispatchGroup
,则剧集不需要以预期的顺序返回,因为它们将分别在同一时间独立地请求。最简单的解决方案是将它们收集在一个数组中,然后按照剧集编号对数组进行排序,然后通知您的代表。