简体   繁体   中英

Swift: loading image asynchronously in UITableViewCell - Autolayout issue

In my UITableViewCell I have a UIImageView that download image asynchronously (with Kingfisher library). It's very similar to Instagram.

在此处输入图片说明

I'm using autolayout and I want to use UITableView.automaticDimension for row height. How should I set constraints so that the height of the cell becomes taller or shorter according to the image? If I set an initial constraint for the UIImageView height and change it once I download the image, I have at leat one element that changes its height to "fill" the space added (or removed) by the UIImageView .

Calculate the aspect ratio preserved height using with actual size of the images and device screen sizes for each one, and update UIImageView height constraint on the UITableViewCell.

Just call feedCell.configure(with: FeedImage) on the tableView(_:cellForRowAt:)

// FeedImage data will be load from your API, in the best practices, you should get actual sizes of the image from your API

struct FeedImage {
    var url: String = ""
    var width: CGFloat = 0.0
    var height: CGFloat = 0.0
}

class FeedCell: UITableViewCell {

    @IBOutlet weak var feedImageView: UIImageView!
    @IBOutlet weak var feedImageViewHeightConstraint: NSLayoutConstraint!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    func configure(with feedImage: FeedImage) {

        feedImageViewHeightConstraint.constant = getAspectRatioPreservedHeight(actualWidth: feedImage.width, actualHeight: feedImage.height)

        feedImageView.loadImage(with: feedImage.url) // Asynchronous image downloading and setting, you can use any library such as SDWebImage, AlamofireImage, Kingfisher or your custom asynchronous image downloader

    }

    // Calculate the aspect ratio preserved height using with actual size of the images and device screen sizes.
    private func getAspectRatioPreservedHeight(actualWidth: CGFloat, actualHeight: CGFloat) -> CGFloat {

        let WIDTH = UIScreen.main.bounds.width
        let HEIGHT = UIScreen.main.bounds.height

        if (actualWidth == 0) { return CGFloat(400.0) }

        let newComputedHeight = (WIDTH*actualHeight)/actualWidth

        if newComputedHeight > (HEIGHT * 0.6) {
            return (HEIGHT * 0.6)
        }

        return newComputedHeight
    }

}

you have to Crop Image Propotionally and than save to KingFisher Cache.

let cached = ImageCache.default.imageCachedType(forKey: url)
        if cached != .none {
            getImageFromCache(key: url) { [weak self] (cachedImage) in
                self?.image = cachedImage
                self?.completionHandler?(cachedImage)
            }
        }
        else {
            getImageFromServer(key: url) { [weak self] (cahcedImage) in
                self?.image = cahcedImage
                ImageCache.default.store(cahcedImage, forKey: self!.url)
                self?.completionHandler?(cahcedImage)
            }
        }





 func getImageFromCache(key:String,complition:@escaping (UIImage)->()) {
        ImageCache.default.retrieveImage(forKey: url, options: nil) { [weak self] (image, cachetype) in

            guard let cachedImage = image , let opCancelled = self?.isCancelled , opCancelled == false  else {
                return
            }
            complition(cachedImage)
        }
    }

    func getImageFromServer(key:String,complition:@escaping (UIImage)->()) {
        if let imageUrl = URL(string: key) {
            KingfisherManager.shared.retrieveImage(with: imageUrl, options: nil, progressBlock: nil) { [weak self] (image, error, cachetype, _ ) in
                if error == nil {
                    guard let cachedImage = image , let opCancelled = self?.isCancelled , opCancelled == false  else {
                        return
                    }


                        let finalheight = (UIScreen.main.bounds.width * CGFloat(cachedImage.size.height)) / CGFloat(cachedImage.size.width)
                        let newImage = cachedImage.resize(targetSize: CGSize(width: UIScreen.main.bounds.width, height: finalheight))
                        complition(newImage)

                }
                else {
                    print("Error ###### == Errror While Downloading Image")
                }
            }
        }
        else {
            print("Error ###### == can't create Url of String")
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM