-2

Im trying to upload a photo to my tableView through a url. The code I have between the "/////" comments is making my UI laggy and slow and Im not understanding why or how to fix it.

I have done some research but this doesnt seem to be working(still lagging)

let userProfileChatImage = generalRoomDataArr[indexPath.row].photoURL

    if let url = NSURL(string: userProfileChatImage!) {

    if let data = NSData(contentsOf: url as URL) {

        DispatchQueue.main.async(execute: {() -> Void in
            imageView.image = UIImage(data: data as Data)
        })


        }
    }

But im not sure exactly if this is the reason or how to implement it or why.

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

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell")



        let usernameLabel = cell?.viewWithTag(1) as! UILabel
        usernameLabel.text = generalRoomDataArr[indexPath.row].username

        let messageLabel = cell?.viewWithTag(2) as! UILabel
        messageLabel.numberOfLines=0 // line wrap
        messageLabel.lineBreakMode = NSLineBreakMode.byWordWrapping
        messageLabel.text = generalRoomDataArr[indexPath.row].message



        //initialize UI Profile Image
        let imageView = cell?.viewWithTag(3) as! UIImageView

        //Make Porfile Image Cirlce
        imageView.layer.cornerRadius = imageView.frame.size.width/2
        imageView.clipsToBounds = true

        /////////////////////////////////////////////

        let userProfileChatImage = generalRoomDataArr[indexPath.row].photoURL

        if let url = NSURL(string: userProfileChatImage!) {

        if let data = NSData(contentsOf: url as URL) {

        imageView.image = UIImage(data: data as Data)


        /////////////////////////////////////////////






        // your cell coding
        return cell!
    }
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
nil
  • 47
  • 1
  • 1
  • 7

2 Answers2

0

You need download the images asynchronous. For this you can use differents libraries like: AlamofireImage or SDWebImage

If you don't want use some library, you can create an extension of UIImageView, for more information visit this answer.

Community
  • 1
  • 1
DiegoQ
  • 1,114
  • 11
  • 20
0

Functions like NSData(contentsOf:) and UIImage(contentsOf:) are synchronous. They do the network request immediately, and don't go on to the next line until the entire network job is done. This freezes the current thread.

Using functions like that on the main thread is a bad idea, as you've discovered.

Apple suggests that you use NSURLSession (URLSession in Swift 3) instead. That class does it's work in the background, and then either invokes a delegate method or a completion handler once the download is complete (both options are available.) By default the delegate method/completion handler is invoked on a background thread, so you need to wrap UI calls in code that sends messages to the main thread.

I have a sample project on Github called Async_demo that shows a very simple example of using URLSession to do a download asynchronously. It deliberately doesn't cache the results so that you can try it over and over. In a real app you would want to save your downloaded images to files on disk, and check to see if they were already downloaded before issuing a new download. You could name your file using a hash of the URL so you could load it from the file if the user tried to display that cell a second time.

As Diego says in his answer, there are also various third-party libraries you can use.

Duncan C
  • 128,072
  • 22
  • 173
  • 272