Parth Saxena
Parth Saxena

Reputation: 71

Swift - Slow UITableView scroll (loading image from device storage)

I have a UITableView populated with cells either containing just a text label or a text label and a UIImage. When the app is run, images are downloaded from my server and stored on the device locally. Every time the app is run, the app checks for new images and downloads them. In my cellForRowAtIndexPath function, I load the image from the device storage on a background thread then update the UI on the main thread.

I don't know if I am doing this right but here is my code for displaying images inside my cellForRowAtIndexPath function:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        for image in self.postsImages {
            if ((image as! NSArray)[0] as! Int == postIDCurrent) {
                // there is an image associated with this post

                let postImage = UIImage(contentsOfFile: (currentArray.lastObject as? String)!)
                dispatch_async(dispatch_get_main_queue(), {
                    cell.postImageView.image = postImage
                    cell.postImageView.clipsToBounds = true
                    cell.postImageView.userInteractionEnabled = true
                    cell.postImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(PostsTableViewController.imageTapped(_:))))
                })
            }
        }
    })

The for and the if statements both just really check if there is an image associated with the current cell we are going to display.

I'm sorry if I'm not providing sufficient information. If you need anything more, please comment.

Anyways, my question is, what am I doing wrong with this code which causes my UITableView to scroll very slow?

Upvotes: 2

Views: 1757

Answers (2)

Alex Curylo
Alex Curylo

Reputation: 4770

Chances are that postImage is much larger than than the bounds of cell.postImageView, so the assignment on the main thread takes a noticeable amount of time to scale it down. Assuming that postImageView's bounds are foreseeable, scaling the image to the correct size in the background thread will be quite likely to sort this out. If you don't have a resizing function handy, this gist looks reasonable.

Upvotes: 4

Chris Wood
Chris Wood

Reputation: 351

Try breaking your for loop:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    for image in self.postsImages {
        if ((image as! NSArray)[0] as! Int == postIDCurrent) {
            // there is an image associated with this post

            let postImage = UIImage(contentsOfFile: (currentArray.lastObject as? String)!)
            dispatch_async(dispatch_get_main_queue(), {
                cell.postImageView.image = postImage
                cell.postImageView.clipsToBounds = true
                cell.postImageView.userInteractionEnabled = true
                cell.postImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(PostsTableViewController.imageTapped(_:))))
            })
            break
        }
    }
})

Upvotes: 0

Related Questions