2017-08-15 21 views
0

ニュースアプリでマルチスレッドに苦労しています。私のアプリケーションは、データが解析されて読み込まれたあとにテーブルビューをスクロールして、その方法が頻繁に起こるとフリーズすることがよくあります。毎回データを読み込むのは間違っていると思います。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 
} 

だから二つの質問がある:どのように私は私のスレッドを配布し、どのように私がすべき必要がありますそれらを呼び出すと、ダウンロードされたすべてのデータがスムーズで素敵なテーブルビューになります。セル内のデータをどのようにリロードする必要がありますか?

+0

インターネットからのデータをメインキューにロードしないでください。 – rmaddy

+0

@rmaddy DispatchQueue.global(qos:.userInitiated).asyncメソッドを追加してjsonObjectを解析するかどうかは関係ありません。私はそれらのフリーズとラグはreloadDataメソッドから来ていると思うが、私はそれなしで動作させる方法を知らない。 –

+0

'NSData contentsOf:'を使わないで、そのスレッド(この場合はメインスレッド)の実行をブロックする。通常の 'NSURLSession'タスクと置き換えてください(そして、データを取得したらまだ正しいセルがあることを再度確認してください) – jcaron

答えて

1

問題は、imageDataがメインスレッドをブロックしていることが原因です。これを解決する最善の方法は、すべてのイメージをイメージキャッシュにダウンロードすることです。そして、私はcellForRowAtIndexPath内からの画像のダウンロードを確実に削除します。

+0

ありがとうございます!画像をプリキャッシングするのが最良の解決策でした! –

+0

私は助けてくれるだろう – OverD

0

バックグラウンドスレッドで解析するデータをダウンロードし、メインスレッドのUIを更新します。

基本的に正しくこれを行うと、すべて正常になります。 メインスレッドでUIをレンダリングする場合、もう一度もう一度チェックする必要があります。

デバッグパネルには、一時停止/再生ボタンがあります。 アプリがフリーズしたときは、すぐにアプリを一時停止してください:

1)あなたのUIメソッドがバックグラウンドスレッドで実行されているかどうかを確認してください。

2)ダウンロードタスクがあるか、またはメインスレッド上でjsonを解析しているかどうかを確認してください。

上記のケースに該当する場合は、正しいものである必要があります。

+0

ありがとう、それは私の多くを助けた!あまりにも悪い私は正しい解決策として2つの答えを選択することはできません –

関連する問題