我有一个应用程序可以从 URL 下载一些信息(即作者姓名、故事标题和封面图片)。我能够从服务器正确下载和解析 JSON,但我卡在了一点。
该应用程序由一个 View Controller (称为 ViewController.swift)和一个类文件(称为 GetStories.swift)组成。一旦应用程序完成从服务器下载和解析 JSON,我希望 View Controller 中的 TableView 重新加载自身 (self.tableView.reloadData())。
我在 GetStories.swift 中设置了一系列完成 block ,它们按顺序完成以下步骤: 1)下载JSON 2)解析JSON 3) 保存到磁盘
func updateUI(){
saveDownloadedAndParsedJSONToDisk {
}
}
func saveDownloadedAndParsedJSONToDisk(completionHandler: @escaping RefreshTableView){
parseJSON {
self.saveDataToJSON()
completionHandler()
}
}
func parseJSON(completionHandler: @escaping ReadyToSave){
downloadJSON { jsonPayload, error in
do {
if let data = jsonPayload {
self.stories = try JSONDecoder().decode(Stories.self, from: data)
if let stories = self.stories {
self.stories = stories
completionHandler()
} else {
print("An error occurred while decoding JSON.")
}
} else if let error = error {
print("Error retrieving data: \(error)")
}
} catch {
print(error.localizedDescription)
}
}
}
func downloadJSON(completionHandler: @escaping NetworkResponse){
let storiesAPIURL = URL(string: "\(wattpadAPIURL)")
var wattpadAPIRequest = URLRequest(url: storiesAPIURL!)
wattpadAPIRequest.httpMethod = "GET"
let session = URLSession.shared
let dataTask = session.dataTask(with: wattpadAPIRequest) { (data : Data?, response : URLResponse?, error : Error?) in
if let data = data {
completionHandler(data, nil)
} else if let error = error {
completionHandler(nil, error)
print(error.localizedDescription)
}
}
dataTask.resume()
}
在 ViewController.swift 中,我正在调用 updateUI()。然后,我在协议(protocol)中调用委托(delegate)方法:
self.storyResults?.delegate?.didFinishFetchingAndParsingData(finished: true)
委托(delegate)方法是这样做的:
func didFinishFetchingAndParsingData(finished: Bool) {
guard finished else {
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.tableView.reloadData()
SVProgressHUD.dismiss()
}
}
因此,如您所见,我使用了 0.5 秒的延迟来重新加载 TableView ,因为我不确定如何判断下载、解析和保存何时完全完成。
如果我不在委托(delegate)方法中使用 0.5 秒的延迟, TableView 会在不适当的时间重新加载,结果不会显示任何结果。因此,以这种方式执行重新加载是行不通的:
DispatchQueue.main.async {
self.tableView.reloadData()
}
执行此操作的正确方法是什么?
提前致谢!
最佳答案
将委托(delegate)调用移至 updateUI 内部的 completionHandler,然后它会在适当的时候被调用。现在你有一个空的 completionHandler。
func updateUI() {
saveDownloadedAndParsedJSONToDisk {
DispatchQueue.main.async {
self.storyResults?.delegate?.didFinishFetchingAndParsingData(finished: true)
}
}
}
...
func didFinishFetchingAndParsingData(finished: Bool) {
guard finished else {
return
}
self.tableView.reloadData()
SVProgressHUD.dismiss()
}
关于ios - 我如何知道何时可以重新加载 TableView ,以便它显示我下载和解析的 JSON 数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55716284/