Hamid Hamid - 2 months ago 12
iOS Question

Swift 3 unclear delay in filling up labels in a collection view

I am reading products data from API and print down the ids to make sure data has been fetched successfully. Then, I put products titles into collection view label.

The strange thing here is that the list of ids are printed very fast. Then the app wait for few seconds till the collectionView is populated.

I couldn't understand why the delay is occurring as I have only 10 products, which should not take any time for loading and I already made a loop over them and printed ids successfully in no time!

The following code shows exactly what I have done yet. I hope someone can help me figure out where is the bottle-nick:

import UIKit

class TestViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@IBOutlet weak var collectionView: UICollectionView!

var jsonData : [[String: Any]] = [[:]]

override func viewDidLoad() {
super.viewDidLoad()

var request = URLRequest(url: URL(string: shopUrl + "/admin/products.json")!)
request.httpMethod = "GET"

URLSession.shared.dataTask(with:request, completionHandler: {(data, response, error) in
if error != nil {
print(error)
} else {
do {
guard let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] else { return }

guard let root = json?["products"] as? [[String: Any]] else { return }
self.jsonData = root
self.collectionView.reloadData()

print("This will be printed very fast!")

for product in root {
guard let id = product["id"] as? Int else { return }
print(id)
}
}
}
}).resume()

}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.jsonData.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let data = self.jsonData[indexPath.row]

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TestCollectionViewCell", for: indexPath) as! TestCollectionViewCell

if let title = data["title"] as? String {
cell.titleLabel.text = title
}

return cell
}
}

Answer

Try call your reloadData in main thread:

DispatchQueue.main.async {
   self.collectionView.reloadData()
}

The problem is that URLSession callback handler is still in background thread so it wont update your UI fast, so you have to switch back to main thread before update any UI after call network request with URLSession

Comments