Ceyhun Ashurbeyli Ceyhun Ashurbeyli - 6 months ago 83
Swift Question

UITableView freezing during scroll in swift

I have this problem about 3-4 weeks. I googled , checked everything but still not working. Please help me!

On every moving scroll

cellForRowAtIndexPath
reloads
tableView
so , it start freezing.

My tableview for
cellForRowAtIndexPath
function is like this:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{

let cell = tableView.dequeueReusableCellWithIdentifier("cell")! as! MoviesTVC
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),{
let dictionary = self.rows[indexPath.row] as? [String: AnyObject]
dispatch_async(dispatch_get_main_queue(),{
cell.setCell(dictionary!)
})

})

return cell
}


The
setCell()
function:

func setCell(dictionary: AnyObject){
let ImgString = dictionary["src"] as? String;
let ImgUrl = NSURL(string: ImgString!);
let ImgData = NSData(contentsOfURL: ImgUrl!)
self.movImg.image = UIImage(data: ImgData!);
self.movName.text = dictionary["name"] as? String;
self.movComment.text = dictionary["caption"] as? String;
}

Answer

You have the wrong bits of code in background async tasks. Currently you are only getting a value from your array in the background, which is a very very fast process...

What you should do is run the difficult tasks in the background, then update the UI in the foreground.

let cell = tableView.dequeueReusableCellWithIdentifier("cell")! as! MoviesTVC
let dictionary = self.rows[indexPath.row] as? [String: AnyObject]
cell.setCell(dictionary!)

return cell


func setCell(dictionary: AnyObject){
    let ImgString = dictionary["src"] as? String;
    let ImgUrl = NSURL(string: ImgString!);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),{
        let ImgData = NSData(contentsOfURL: ImgUrl!)
        let image = UIImage(data: ImgData!);
        //Possibly resize the image here in the background task
        //so that the cpu doesn't need to scale it in the UI thread
        dispatch_async(dispatch_get_main_queue(),{
            self.movImg.image = image
        })
    })
    self.movName.text = dictionary["name"] as? String;
    self.movComment.text = dictionary["caption"] as? String;
}

Edit: To answer your question in comments. The easiest solution would be to add an attribute to the dictionary for each cell that is "image". Then when you are loading the cell if the "image" attribute of the dictionary exists then you can just load that image into your cell. If it doesn't exist then download it and save it to the dictionary, then add it to your cell.

A harder solution to that would be to download the images to a local resource location. Then use imageNamed to load the image from file. This will take care of caching and memory releasing for you. That would be the better option.

Even better would be to use CoreData. In any of these solutions you will have to manage clearing file storage when you are running low.