I am new to Swift and have set up a tableView which pulls data from a JSON feed and loads it into the table.
The table loads fine however when there are more than say 10 cells in the table, it becomes slow and somewhat laggy, particularly it reaches the top and bottom (I imagine this is where a cell is being reused).
Would someone be so kind as to take a look at my code and explain why it may be doing this? I have implemented SDWebImage which has helped but its still not ideal:
var tableData = [String]()
var tableAvailable = [String]()
var tableImages = [String]()
var tableDesc = [String]()
var tablePin = [String]()
override func viewDidAppear(_ animated: Bool) {
let nib = UINib(nibName: "vwTblCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "cell")
self.tableData.removeAll(keepingCapacity: false)
self.tableAvailable.removeAll(keepingCapacity: false)
self.tableImages.removeAll(keepingCapacity: false)
self.tableDesc.removeAll(keepingCapacity: false)
let url = NSURL(string: "https://www.asmserver.co.uk/sally/parsexml.php")!
let task = URLSession.shared.dataTask(with: url as URL) { (data, response, error) -> Void in
if let urlContent = data {
do {
if let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: []) as? [[String:AnyObject]] {
for item in jsonResult {
guard let name = item["display-name"] as? String else { continue }
if (self.tableData.contains(item["display-name"] as! String)) {
}else{
self.tableData.append(name)
guard let available = item["status"] as? String else { continue }
self.tableAvailable.append(available)
guard let image = item["image-url"] as? String else { continue }
self.tableImages.append(image)
guard let desc = item["short-desc"] as? String else { continue }
self.tableDesc.append(desc)
guard let pin = item["agent-id"] as? String else { continue }
self.tablePin.append(pin)
}
}
}
} catch {
print("JSON serialization failed")
}
} else {
print("ERROR FOUND HERE")
}
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.reloadData()
})
self.tableView.isUserInteractionEnabled = true
}
task.resume()
}
override func viewDidLoad() {
if revealViewController() != nil {
menuButton.addTarget(self.revealViewController(), action: #selector(SWRevealViewController.revealToggle(_:)), for: UIControlEvents.touchUpInside)
self.view.addGestureRecognizer(revealViewController().panGestureRecognizer())
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData.count
}
// 3
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TblCell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! TblCell
cell.lblCarName.text = tableData[indexPath.row]
let url = NSURL(string: "\(tableImages[indexPath.row])")
if let data = NSData(contentsOf: url as! URL) {
cell.imgCarNane.sd_setImage(with: (string: url) as URL!)
}
cell.pinLabel.text = tablePin[indexPath.row]
if(tableAvailable[indexPath.row] == "Busy"){
cell.onlineIcon.image = UIImage(named: "livefeedofflineicon.png")
}
if (indexPath.row % 2 == 0){
cell.contentView.backgroundColor = UIColor(red: 237/255.0, green: 234/255.0, blue: 234/255.0, alpha: 1.0)
}
return cell
}
// 4
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Row \(indexPath.row) selected")
}
// 5
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 140
}
I suppose in your cellForRowAt
this line is making it a bit slow
if let data = NSData(contentsOf: url as! URL) {
cell.imgCarNane.sd_setImage(with: (string: url) as URL!)
}
NSData(contentsOf: url as! URL)
is making it a bit slow
Just remove the if let
clause as SDWebImage
handles the nil url itself and just write
cell.imgCarNane.sd_setImage(with: (string: url) as URL!)
So your cellForRowAt
datasource method will become like this now
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TblCell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! TblCell
cell.lblCarName.text = tableData[indexPath.row]
let url = NSURL(string: "\(tableImages[indexPath.row])")
cell.imgCarNane.sd_setImage(with: (string: url) as URL!)
cell.pinLabel.text = tablePin[indexPath.row]
if(tableAvailable[indexPath.row] == "Busy"){
cell.onlineIcon.image = UIImage(named: "livefeedofflineicon.png")
}
if (indexPath.row % 2 == 0){
cell.contentView.backgroundColor = UIColor(red: 237/255.0, green: 234/255.0, blue: 234/255.0, alpha: 1.0)
}
return cell
}
I hope that fixes the lag