Похоже, вы могли бы извлечь выгоду из некоторого кэширования изображений. Есть несколько способов сделать это, но из вашего примера не похоже, что вам нужно будет добавлять всю библиотеку, чтобы сделать это. Вы можете сделать это простым способом, используя NSCache.
Я создал класс с именем ImageCache, и в данном случае он является одноэлементным, поэтому кэш доступен во всем приложении.
import UIKit
class ImageCache: NSObject {
static let sharedImageCache = ImageCache()
// Initialize cache, specifying that your key type is AnyObject
// and your value type is AnyObject. This is because NSCache requires
// class types, not value types so we can't use <URL, UIImage>
let imageCache = NSCache<AnyObject, AnyObject>()
// Here we store the image, with the url as the key
func add(image: UIImage, for url: URL) {
// we cast url as AnyObject because URL is not a class type, it's a value type
imageCache.setObject(image, forKey: url as AnyObject)
}
// This allows us to access the image from cache with the URL as the key
// (e.g. cache[URL])
func fetchImage(for url: URL) -> UIImage? {
var image: UIImage?
// Casting url for the same reason as before, but we also want the result
// as an image, so we cast that as well
image = imageCache.object(forKey: url as AnyObject) as? UIImage
return image
}
}
Так что теперь у нас есть относительно простое кеширование. Теперь о том, как его использовать:
func getChampionThumbnailImage (championId: Int) -> UIImage {
var image: UIImage!
let urlString = ApiHelper.getChampionThumbnailImageApiLink(championId: championId)
let url = URL(string: urlString)
// Before, downloading the image, we check the cache to see if it exists and is stored.
// If so, we can grab that image from the cache and avoid downloading it again.
if let cachedImage = ImageCache.sharedImageCache.fetchImage(for: url) {
image = cachedImage
return image
}
let session = URLSession.shared
let semaphore = DispatchSemaphore(value: 0)
session.dataTask(with: url!) {(data, response, error) in
if error != nil {
print("ERROR")
semaphore.signal()
}
else {
image = UIImage(data: data!)!
// Once the image is successfully downloaded the first time, add it to
// the cache for later retrieval
ImageCache.sharedImageCache.add(image: image, for: url!)
semaphore.signal()
}
}.resume()
semaphore.wait()
session.finishTasksAndInvalidate()
return image
}
Причина повторной загрузки изображений в том, что в табличном представлении нет неограниченных ячеек. Что происходит, когда вы прокручиваете вниз, ячейки, которые выходят за пределы экрана, затем перерабатываются и снова используются, поэтому, когда вы прокручиваете обратно вверх, изображения нужно снова захватывать, потому что они были очищены.
Вы можете избежать повторной загрузки изображений, внедрив кэширование.
Еще один способ избежать неправильных изображений - установить нулевое представление изображения перед повторной загрузкой изображения. Например:
cell?.mainChampImageView = nil
cell?.mainChampImageView.image = businessLayer.getChampionThumbnailImage(championId: mainChampion.key)
Все вышеперечисленное, наряду с проверкой правильности снятия ячеек с ячеек, должны решить вашу проблему.