Rahul Rawat
Rahul Rawat

Reputation: 997

UITableView is not smoothly when using downloading images

I am new in IOS development using Swift. I created 1 UITableView and displaying images after downloading data. But it is not smooth and some time images are displaying in wrong place when i am scrolling.

I am using AlamofireImage library for image downloading and displaying. Is there any fast library?

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

    let cell:HomePageCell = tableView.dequeueReusableCell(withIdentifier: "HomePage", for: indexPath) as! HomePageCell

    cell.configure( homeData[0], row: indexPath, screenSize: screenSize,
                    hometableview: self.homeTableView);

    return cell
}


import UIKit
import Alamofire
import AlamofireImage

class HomePageCell: UITableViewCell {



@IBOutlet weak var bannerImage: UIImageView!

func configure(_ homeData: HomeRequest, row: IndexPath, screenSize: CGRect, hometableview: UITableView) {


   let callData = homeData.banner_lead_stories[(row as NSIndexPath).row]
   let url = Constants.TEMP_IMAGE_API_URL + callData.lead_story[0].bg_image_mobile;


    if( !callData.lead_story[0].bg_image_mobile.isEmpty ) {

        if bannerImage?.image == nil {

            let range = url.range(of: "?", options: .backwards)?.lowerBound
            let u = url.substring(to: range!)

            Alamofire.request(u).responseImage { response in
                debugPrint(response)

                //print(response.request)
                // print(response.response)
                // debugPrint(response.result)

                if let image = response.result.value {
                    //   print("image downloaded: \(image)")

                    self.bannerImage.image = image;

                    self.bannerImage.frame  = CGRect(x: 0, y: 0, width: Int(screenSize.width), height: Int(screenSize.width/1.4))

                }
            }

        }

    } else {
        self.bannerImage.image = nil;
    }
}

 }

Upvotes: 1

Views: 1129

Answers (5)

James Rochabrun
James Rochabrun

Reputation: 4377

Use this extension to cache your images, and also don't forget to update any UI on the main thread.

let imageCache = NSCache<NSString, UIImage>()
extension UIImageView {
    func loadImageUsingCacheWithURLString(_ URLString: String, placeHolder: UIImage?) {
        self.image = nil
        if let cachedImage = imageCache.object(forKey: NSString(string: URLString)) {
            self.image = cachedImage
            return
        }  
        if let url = URL(string: URLString) {
            URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
                //print("RESPONSE FROM API: \(response)")
                if error != nil {
                    print("ERROR LOADING IMAGES FROM URL: \(error)")
                    DispatchQueue.main.async {
                        self.image = placeHolder
                    }
                    return
                }
                DispatchQueue.main.async {
                    if let data = data {
                        if let downloadedImage = UIImage(data: data) {
                            imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
                            self.image = downloadedImage
                        }
                    }
                }
            }).resume()
        }
    }
}

Upvotes: 1

Govind Prajapati
Govind Prajapati

Reputation: 957

Try SDWebImage library it will save images in catch automatically and your tableView will work smoothly.

Github link -> https://github.com/rs/SDWebImage

Install pod:

platform :ios, '7.0'
pod 'SDWebImage', '~>3.8'

Just import SDWebImage like:

@import SDWebImage

And use like this:

imageView.sd_setImage(with: URL(string: "http://www.example.com/path/to/image.jpg"), placeholderImage: UIImage(named: "placeholder.png"))

I used it in many live projects and it works like a charm :)

Upvotes: 1

Jagdeep
Jagdeep

Reputation: 1178

You can use SDWebImage for downloading the image array and add a placeholder image for the time being in imageView. this is function

 public func sd_setImageWithURL(url: NSURL!, placeholderImage placeholder: UIImage!)

and it is as easy to use as

 myImageView.sd_setImageWithURL(NSURL(string:image), placeholderImage:UIImage(named:"qwerty"))

make sure to reset you imageView in tableView delegate cellforRowAtIndexpath method by setting imageview image to nil

myImageView.image = nil
//now set image in imageView
myImageView.sd_setImageWithURL(NSURL(string:image), placeholderImage:UIImage(named:"qwerty"))

this avoids the image duplicating and weird behave of images as imageview of every cell is being reset before reusing. Github link -> https://github.com/rs/SDWebImage

Upvotes: 2

Vlad Pulichev
Vlad Pulichev

Reputation: 3272

It can be not smooth, because you need to cache your images and make a downloading process not in main thread(read about GCD). For caching you can go two ways (atleast):

1) Make your own array of images where they will be cached

2) Use KingFisher for example click. It will cache your images. For example:

yourImageView.kf.setImage(with: URL) // next time, when you will use image with this URL, it will be taken from cache.

Hope it helps

Upvotes: 3

swapnil patel
swapnil patel

Reputation: 394

You have to use multithreading.Only UI is set in main thread, downloading image in background is in another thread.By this way you can solve your problem.

Upvotes: 1

Related Questions