ニュースアプリでマルチスレッドに苦労しています。私のアプリケーションは、データが解析されて読み込まれたあとにテーブルビューをスクロールして、その方法が頻繁に起こるとフリーズすることがよくあります。毎回データを読み込むのは間違っていると思います。JSONデータの解析中にUITableViewでスクロール中にフリーズする
最初の部分:
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
}
の私のviewDidLoadです配列から構造体へ:
self.jsonData.append(jsonObjects(id: id, date: date, title: title,
imageURL: imageURL))
}
}
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
})
とdownloadJsonWithURLは単純です:
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でいることをI入力:
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
}
だから二つの質問がある:どのように私は私のスレッドを配布し、どのように私がすべき必要がありますそれらを呼び出すと、ダウンロードされたすべてのデータがスムーズで素敵なテーブルビューになります。セル内のデータをどのようにリロードする必要がありますか?
インターネットからのデータをメインキューにロードしないでください。 – rmaddy
@rmaddy DispatchQueue.global(qos:.userInitiated).asyncメソッドを追加してjsonObjectを解析するかどうかは関係ありません。私はそれらのフリーズとラグはreloadDataメソッドから来ていると思うが、私はそれなしで動作させる方法を知らない。 –
'NSData contentsOf:'を使わないで、そのスレッド(この場合はメインスレッド)の実行をブロックする。通常の 'NSURLSession'タスクと置き換えてください(そして、データを取得したらまだ正しいセルがあることを再度確認してください) – jcaron