gurkan stack
gurkan stack

Reputation: 225

JSON Data to Table View is too slow

I am showing JSON data in TableView but the application is slow. It is waiting 5-10 seconds before display. I am getting this error in Xcode output:

2017-06-05 12:49:47.505 Ekstraders[1167:137558] This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.


 Stack:(
    0   CoreFoundation                      0x000000010ad78b0b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x0000000108020141 objc_exception_throw + 48
    2   CoreFoundation                      0x000000010ade1625 +[NSException raise:format:] + 197
    3   Foundation                          0x0000000107d1917b _AssertAutolayoutOnAllowedThreadsOnly + 105
    4   Foundation                          0x0000000107d18f0f -[NSISEngine _optimizeWithoutRebuilding] + 61
    5   Foundation                          0x0000000107b487e6 -[NSISEngine optimize] + 108
    6   Foundation                          0x0000000107d16ef4 -[NSISEngine performPendingChangeNotifications] + 84
    7   UIKit                               0x00000001085b5412 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1787
    8   QuartzCore                          0x000000010dce6904 -[CALayer layoutSublayers] + 146
    9   QuartzCore                          0x000000010dcda526 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 370
    10  QuartzCore                          0x000000010dcda3a0 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
    11  QuartzCore                          0x000000010dc69e92 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
    12  QuartzCore                          0x000000010dc96130 _ZN2CA11Transaction6commitEv + 468
    13  QuartzCore                          0x000000010dc9642c _ZN2CA11Transaction14release_threadEPv + 214
    14  libsystem_pthread.dylib             0x000000010c065413 _pthread_tsd_cleanup + 544
    15  libsystem_pthread.dylib             0x000000010c06514d _pthread_exit + 152
    16  libsystem_pthread.dylib             0x000000010c0636d1 pthread_attr_getschedpolicy + 0
    17  libsystem_pthread.dylib             0x000000010c0630f1 start_wqthread + 13
)

ViewController.swift:

import UIKit


class FirstViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {

    @IBOutlet weak var tableView: UITableView!

    var tbCount = 0

    var myMp3s = [Mp3]()


    override func viewDidLoad() {
        super.viewDidLoad()


        tableView.dataSource = self
        tableView.delegate = self


        let url = URL(string: "example.php")

         DispatchQueue.main.async() { //JSON to Mp3 object.


        URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
            guard let data = data, error == nil else { return }


            do {
                let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
                let posts = json["server_response"] as? [[String: Any]] ?? []

                for i in posts {

                    print(i["id"]!)

                    let mp3 = Mp3(id: i["id"] as! String, category: i["kategori"] as! String)

                    self.myMp3s.append(mp3)


                }

                self.tableView.reloadData()
                self.tableView.tableFooterView = UIView(frame: .zero)

                print("counte", self.myMp3s.count)


            } catch let error as NSError {
                print(error)
            }
        }).resume()

        }

    }



    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myMp3s.count

    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

        var height:CGFloat = CGFloat()

        height = 100
        return height
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {



        let cell  = UITableViewCell()
        cell.backgroundColor =  UIColor.darkGray



        //Design 
        cell.textLabel?.text = self.myMp3s[indexPath.row].category 

        cell.textLabel?.backgroundColor = .red
        cell.textLabel?.layer.borderWidth = 3
        cell.textLabel?.layer.borderColor = UIColor.lightGray.cgColor
        cell.textLabel?.heightAnchor.constraint(equalToConstant: 50).isActive = true
        cell.textLabel?.widthAnchor.constraint(equalToConstant: 200).isActive = true


        cell.textLabel?.layer.cornerRadius = 10
        cell.textLabel?.clipsToBounds = true
        cell.textLabel?.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = true
        cell.textLabel?.centerXAnchor.constraint(equalTo: cell.centerXAnchor).isActive = true

        cell.textLabel?.textAlignment = .center
        cell.textLabel?.textColor = .white
        cell.textLabel?.font = UIFont.boldSystemFont(ofSize: 16.0)

        return cell


    }


    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print(myMp3s[indexPath.row].category)
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

I can show JSON data in tableview, no problem but the problem is that it is too slow. It is waiting before display. How can I solve this problem? Where am I wrong?

Upvotes: 1

Views: 779

Answers (2)

Saheb Roy
Saheb Roy

Reputation: 5957

  1. The data you are receiving is big, or if it is small you might be experiencing network problems.To check the amount of data and average time, fetch that data using a REST client. You can use Postman or ARC to know the data.
  2. As everyone else mentioned, you are getting that error, (Not crash) I believe, as you are making UI changes from a background thread. Now the network call you are making is an asynchronous call, meaning it is getting called in the background thread, once it is initiated. You should always make UI changes from the main thread.

    DispatchQueue.main.async {
       self.tableView.reloadData()
       self.tableView.tableFooterView = UIView(frame: .zero)
    }
    

Upvotes: 1

Ozgur Vatansever
Ozgur Vatansever

Reputation: 52153

URLSession.shared.dataTask is executing the completion handler in a background thread. This leads to unexpected issues because operations affecting the UI must be done by the main thread.

Thus, you should wrap those parts with DispatchQueue.main.async {}:

DispatchQueue.main.async {
  self.tableView.reloadData()
  self.tableView.tableFooterView = UIView(frame: .zero)
}

Upvotes: 2

Related Questions