Ios 在分析JSON数据期间,在UITableView中滚动时冻结
我在新闻应用程序中努力使用多线程。问题是——当我在解析和加载数据后滚动表视图时,我的应用程序经常会冻结,并且它的方式太频繁。我觉得每次重新加载数据都有点不对 第一部分:Ios 在分析JSON数据期间,在UITableView中滚动时冻结,ios,json,swift,multithreading,uitableview,Ios,Json,Swift,Multithreading,Uitableview,我在新闻应用程序中努力使用多线程。问题是——当我在解析和加载数据后滚动表视图时,我的应用程序经常会冻结,并且它的方式太频繁。我觉得每次重新加载数据都有点不对 第一部分: final let urlString = "http://api.to.parse" 在这里,我创建结构数组来填充数据 struct jsonObjects { var id : Int var date : String var title : String
final let urlString = "http://api.to.parse"
在这里,我创建结构数组来填充数据
struct jsonObjects {
var id : Int
var date : String
var title : String
var imageURL : URL
}
var jsonData = [jsonObjects]()
这是我的视图加载的tableView
override func viewDidLoad() {
super.viewDidLoad()
// MARK : - Download JSON info on start
JsonManager.downloadJsonWithURL(urlString: urlString, сompletion: {(jsonArray) -> Void in
guard let data = jsonArray else { print("Empty dude"); return;}
for jsonObject in data {
if let objectsDict = jsonObject as? NSDictionary {
guard
let id = objectsDict.value(forKey: "id") as? Int,
let date = objectsDict.value(forKey: "date") as? String,
let titleUnparsed = objectsDict.value(forKey: "title") as? NSDictionary,
let title = (titleUnparsed as NSDictionary).value(forKey: "rendered") as? String,
let imageString = objectsDict.value(forKey: "featured_image_url") as? String,
let imageURL = NSURL(string: imageString) as URL?
else {
print("Error connecting to server")
return
}
在这里,我将填充结构附加到数组:
self.jsonData.append(jsonObjects(id: id, date: date, title: title,
imageURL: imageURL))
}
}
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
})
下载的JSONWithURL是:
class JsonManager {
class func downloadJsonWithURL(urlString: String, сompletion: @escaping (NSArray?) -> Void) {
guard let url = NSURL(string: urlString) else { print("There is no connection to the internet"); return;}
URLSession.shared.dataTask(with: url as URL, completionHandler: { (data, response, error) -> Void in
guard let parseData = data else { print("There is no data"); return;}
if let jsonObj = try? JSONSerialization.jsonObject(with: parseData, options: .allowFragments)
as? NSArray {
сompletion(jsonObj)
}
}).resume()
}
最后,我在TableViewCell中输入:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return jsonData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "newscell") as? NewsTableViewCell else {
fatalError("Could not find cell by identifier")
}
guard let imageData = NSData(contentsOf: jsonData[indexPath.row].imageURL) else {
fatalError("Could not find image")
}
cell.newsTitleLabel.text = self.jsonData[indexPath.row].title
cell.newsTitleLabel.font = UIFont.boldSystemFont(ofSize: 20.0)
cell.newsImageView.image = UIImage(data: imageData as Data)
return cell
}
所以这里有两个问题:我应该如何分配我的线程,我应该如何调用它们,这样我就可以用所有下载的数据获得平滑而漂亮的tableview?如何在单元格中重新加载数据?下载数据,在后台线程中解析,在主线程上更新UI 基本上,如果你这样做正确,一切都会好起来。 所以,若要在主线程上呈现UI,可能需要再次检查 在调试面板上,有暂停/播放按钮。 因此,每当应用程序冻结时,请尝试立即暂停应用程序: 1) 然后检查您的UI方法是否在后台线程上运行 2) 检查下载任务或解析json是否在主线程上进行
如果它属于上述情况,则需要正确。您的问题是由imageData阻塞主线程引起的。解决此问题的最佳方法是将所有图像下载到图像缓存中。我当然会删除CellForRowatineXpath中的图像下载。永远不要在主队列上从Internet加载数据。@rmaddy似乎我是否添加DispatchQueue.global(qos:.userInitiated)。异步方法来解析jsonObject并不重要。我认为所有这些冻结和延迟都来自于重载数据方法,但我不知道如何在没有它们的情况下使其工作。如果不使用
NSData内容,它将阻止该线程(本例中的主线程)上的执行。只需将其替换为常规的NSURLSession
任务(并在获得数据后再次检查您是否仍然拥有正确的单元格)@jcaron那么我是否需要再创建一个datatask(withcompletionhandler:inside parsing Close?您可以为要加载的每个图像创建一个,是的。当然,在实际将图像分配给UIImageView
之前,您可以切换回主线程。请注意,如果您使用缓存库,则不会出现问题,它可能会在幕后为您这样做。非常感谢您uch!预缓存图像是最好的解决方案!我很高兴我能帮上忙谢谢你这么多,它帮了我很多!可惜我不能选择两个答案作为正确的解决方案