swift tableviewcell中imageview自适应

2020-05-16  本文已影响0人  松龄学编程

自动布局中,imageview根据图片的宽高自适应高度。需要提前知道图片的宽高,可以服务器返回添加字段。这里提供一种思路,提前使用kingfisher下载所有图片再刷新表,可以解决这个问题。

private func downloadImages(datas: [SquareModel]) {
        let group = DispatchGroup()
        var heightCache: [String: CGSize] = [:]
        let queue = DispatchQueue(label: "SafeArrayQueue", attributes: .concurrent)
        let downloader = ImageDownloader.default
        let imageUrls = datas.compactMap { (model) -> [String]? in
            return model.pathArrWithoutVideo
        }.flatMap { (urls) -> [String] in
            return urls
        }
        for imageUrl in imageUrls {
            if let url = URL(string: imageUrl) {
                group.enter()
                downloader.downloadImage(with: url) { (result) in
                    switch result {
                    case .success(let value):
                        queue.async(group: group, qos: .userInteractive, flags: .barrier) {
                            heightCache[imageUrl] = value.image.size
                            group.leave()
                        }
                    case .failure(_):
                        group.leave()
                    }
                    
                }
            }
        }
        let videoUrls = datas.filter { (model) -> Bool in
            return model.hasVideo
        }.map { (model) -> String in
            return model.videoCoverUrl
        }
        for videoUrl in videoUrls {
            if let url = URL(string: videoUrl) {
                group.enter()
                downloader.downloadImage(with: url) { (result) in
                    switch result {
                    case .success(let value):
                        queue.async(group: group, qos: .userInteractive, flags: .barrier) {
                            heightCache[videoUrl] = value.image.size
                            group.leave()
                        }
                    case .failure(_):
                        group.leave()
                    }
                    
                }
            }
        }
        group.notify(queue: .main) { [weak self] in
            self?.viewModel.heightCache.merge(heightCache, uniquingKeysWith: { (old, new) -> CGSize in
                return new
            })
            self?.contentView.tableView.reloadData()
        }
    }

上边的方法,需要依赖图片服务器的速度,如果图片服务器性能不是很好的话,会影响加载速度。这里可以先只是获取图片的size,不做下载。通过url获取图片size,方法如下:

func getImageSizeWithURL(url: URL)-> CGSize {
        var imageSize: CGSize = .zero

        guard let imageSourceRef = CGImageSourceCreateWithURL(url as CFURL, nil)
            else { return imageSize }
        
        guard let imagePropertie = CGImageSourceCopyPropertiesAtIndex(imageSourceRef, 0, nil)  as? Dictionary<String, Any>
            else { return imageSize }
        
        imageSize.width = CGFloat((imagePropertie[kCGImagePropertyPixelWidth as String] as! NSNumber).floatValue)
        imageSize.height = CGFloat((imagePropertie[kCGImagePropertyPixelHeight as String] as! NSNumber).floatValue)
        return imageSize
    }

而且,不需要所有图片的url,都缓存宽高,过滤一下,需要获取宽高的图片。更新下,之前的代码

func cacheHeight(datas: [SquareModel], completionHandler: @escaping ([SquareModel]) -> Void) {
        let group = DispatchGroup()
        var heightCache: [String: CGSize] = [:]
        let queue = DispatchQueue(label: "SafeArrayQueue", attributes: .concurrent)
        let imageUrls = datas.compactMap { (model) -> [String]? in
            return model.pathArrWithoutAudioVideo
        }.flatMap { (urls) -> [String] in
            return [urls.first ?? ""]
        }
        for imageUrl in imageUrls {
            if let url = URL(string: imageUrl) {
                group.enter()
                let size = getImageSizeWithURL(url: url)
                queue.async(group: group, qos: .userInteractive, flags: .barrier) {
                    heightCache[imageUrl] = size
                    group.leave()
                }
            }
        }
        let videoUrls = datas.filter { (model) -> Bool in
            return model.hasVideo
        }.map { (model) -> String in
            return model.videoCoverUrl
        }
        for videoUrl in videoUrls {
            if let url = URL(string: videoUrl) {
                group.enter()
                let size = getImageSizeWithURL(url: url)
                queue.async(group: group, qos: .userInteractive, flags: .barrier) {
                    heightCache[videoUrl] = size
                    group.leave()
                }
            }
        }
        group.notify(queue: .main) { [weak self] in
            self?.viewModel.heightCache.merge(heightCache, uniquingKeysWith: { (old, new) -> CGSize in
                return new
            })
            completionHandler(datas)
        }
    }

经测试,优化后,速度飞快,很稳定。

上一篇 下一篇

猜你喜欢

热点阅读