Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在分析JSON数据期间,在UITableView中滚动时冻结_Ios_Json_Swift_Multithreading_Uitableview - Fatal编程技术网

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!预缓存图像是最好的解决方案!我很高兴我能帮上忙谢谢你这么多,它帮了我很多!可惜我不能选择两个答案作为正确的解决方案