自动布局中,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)
}
}
经测试,优化后,速度飞快,很稳定。
网友评论