Я создаю приложение, которое отображает картинки в виде коллекции.Я загружаю JSON из общедоступного API GIPHY, затем получаю данные из каждого отдельного URL-адреса GIF и использую FLAnimatedImage
для сохранения данных в UIImageView
перед их отображением в представлении коллекции.
Iразветвил FLAnimatedImage
pod
и добавил NSCoding
протоколы, чтобы данные можно было архивировать в Core Data.
В моем collectionView
я использую fetchedResultsController
для извлечения объектов, которые заполняютсяmy collectionView
.
Из-за подкачки мой API запрашивает новые изображения каждый раз, когда я получаю полпути вниз по изображениям в моем collectionView
(один столбец, одна строка) в cellForItemAt
.
Вызов для получения новых изображений является асинхронным, и как только он возвращается с результатами из fetchRequest
, я обновляю представление коллекции.Это не блокирует основной поток.
Теперь вот проблема: я сохраняю каждый GIF, как только получаю данные из задачи загрузки в виде FLAnimatedImage
в моем стеке данных ядра.Теперь его разархивирование приводит к повторному запуску создания FLAnimatedImage для каждого изображения, что приводит к значительной загрузке ЦП, поскольку проблема в создании FLAnimatedImage
очень загружает ЦП и поэтому не архивирует его из стека.Таким образом, обе эти операции выполняются для новых пакетов изображений во время подкачки, и в итоге мое приложение вылетает.
Замедление происходит при каждом вызове fetchedResultsController.object(at: indexPath)
, и я использую backgroundContext
, поэтому я знаю, что это не потокЯ на.Я думаю, что это просто общая загрузка процессора, которая вызывает сбой.Но разве fetchedResultsController
не должен был вытянуть сущность из стека?Почему он разархивирует его и создает тип атрибута (FLAnimatedImage) в вызове fetchedResultsController.object(at: indexPath)
?
Есть ли способ сохранить FLAnimatedImage
в стеке, который не потребует его повторного создания каждый разЯ вытаскиваю его из стека с помощью fetchedResultsController.object(at: indexPath)
?
Можете ли вы придумать стратегию, которая может помочь?
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GSGifCollectionViewCell", for: indexPath) as! GSGifCollectionViewCell
let gifObject:NSManagedObject = self.fetchedResultsController.object(at: indexPath)
gifObject.managedObjectContext?.perform {
let gsGifObject = gifObject as? GSGif
DispatchQueue.main.async {
cell.imageView.animatedImage = gsGifObject?.image
cell.rankLabel.text = "\(gsGifObject?.rank ?? 0)"
}
}
if let totalObjectsForSectionZero = fetchedResultsController.sections?[0].numberOfObjects {
self.checkCurrentIndexPathAndGetMoreGifsIfNeccessary(indexPath: indexPath, totalObjects:totalObjectsForSectionZero)
}
return cell
}
Есть ли что-то, что я делаю неправильно?
Вот мой архивный код:
#import "FLAnimatedImage+NSCoding.h"
@implementation FLAnimatedImage (NSCoding)
static NSString *const kFLAnimatedImageCodingData = @"kFLAnimatedImageCodingData";
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
NSData *data = [aDecoder decodeObjectForKey:kFLAnimatedImageCodingData];
return [self initWithAnimatedGIFData:data];
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.data forKey:kFLAnimatedImageCodingData];
}
@end
Это приводит к блокировке основного потока - [self initWithAnimatedGIFData: data];