#ios #swift #api #caching #uikit
Вопрос:
Я создаю приложение в ios, в котором загружаю изображения из api с помощью UITableView и UITableViewCell.
Поскольку UITableView повторно использует ячейки, при быстрой прокрутке появлялись старые изображения. Чтобы предотвратить это, я установил изображение по умолчанию, используя системный образ(символы SF).
Я также использую кэш для хранения URL-адресов изображений.
Все работает так, как должно, но теперь я думаю об этом, я каждый раз отправляю сетевой запрос для получения этого системного изображения, что кажется невероятно неэффективным, так как я использовал кэш, чтобы в первую очередь уменьшить общее количество сетевых вызовов.
Есть ли способ обойти это или это компромисс, который я должен сделать?
Код приведен ниже.
//use default image from SF symbols
let defaulticon = UIImage(systemName: "photo")?.withTintColor(.gray, renderingMode: .alwaysOriginal)
DispatchQueue.main.async {
cell.mealImage.image = defaulticon
}
guard cell.meal?.strMealThumb != nil else {
print("Category Image doesn't exist")
return
}
//use cache
if let imageData = model.imagecache.object(forKey: cell.meal!.strMealThumb as NSString) {
print("using cache")
DispatchQueue.main.async {
cell.mealImage.image = imageData
}
}
else {
let url = URL(string: cell.meal!.strMealThumb)
let session = URLSession.shared.dataTask(with: url!) { data, response, error in
if error == nil amp;amp; data != nil {
let image = UIImage(data: data!)
//self.model.imagecache[cell.meal!.strMealThumb] = image
self.model.imagecache.setObject(image!, forKey: cell.meal!.strMealThumb as NSString)
DispatchQueue.main.async {
cell.mealImage.image = image
}
}
}
session.resume()
}
}
Комментарии:
1. Я был бы очень удивлен, если бы для создания образа системы потребовался сетевой вызов. Системные образы должны быть по-прежнему пригодны для использования, если устройство отключено (скажем, в режиме полета). Тем не менее, я могу себе представить, что для получения образа системы может потребоваться вызов межпроцессной связи.
Ответ №1:
Переопределите prepareForReuse
метод UITableViewCell
и добавьте код в эту функцию для очистки неотправленных данных, которые могли сохраниться после предыдущего использования ячейки. В вашем примере назначьте изображение по умолчанию в этой функции, чтобы получить лучший результат.
Ответ №2:
Вы спросили:
Я установил изображение по умолчанию, используя системный образ(символы SF).
…
Все работает так, как должно, но теперь я думаю об этом, я каждый раз отправляю сетевой запрос для получения этого системного изображения, что кажется невероятно неэффективным, так как я использовал кэш, чтобы в первую очередь уменьшить общее количество сетевых вызовов.
Нет, UIImage(systemName:)
не делает сетевой запрос. И он сам кэширует изображение, как говорится в документации:
Этот метод проверяет системные кэши на наличие изображения с указанным именем и возвращает вариант этого изображения, который лучше всего подходит для главного экрана. Если соответствующий объект изображения еще не находится в кэше, этот метод создает изображение из указанного образа системного символа. Система может очистить кэшированные данные изображений в любое время, чтобы освободить память. Очистка выполняется только для изображений, которые находятся в кэше, но в данный момент не используются.
FWIW, вы можете эмпирически убедиться, что это не выполняет сетевой запрос, отключаясь от сети и пытаясь ее использовать. Вы увидите, что он отлично работает, даже когда отключен.
FWIW, есть очень небольшой прирост производительности (менее миллисекунды?) сохраняя ссылку на этот тонированный образ системы и повторно используя его, вместо того, чтобы извлекать кэшированный образ системы и повторно тонировать его. Но улучшение производительности незначительно.