Memory issue when working with a large UIImage array

I store about 100 UIImage in one array. I know that there is a problem with the use of memory, which ultimately leads to the crash of the application, especially on older devices (iPhone 4s). As for User Experience , saving all UIImages to DocumentsDirectory is not an option (it takes too much time). Therefore, I was thinking about "merging" these two methods. Wait until I get a warning about memory usage, stop storing images in my array, and then start writing to disk. I cannot find the correct way to handle Memory leak/warning/usage call

  override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() print("memory warning") } 

When I test on a real device, it just crashes - without calling a method. Any suggestions?

+5
source share
1 answer

Try using the image cache library. Comparison of the most popular here: https://bpoplauschi.wordpress.com/2014/03/21/ios-image-caching-sdwebimage-vs-fastimage/

My experience: SDWebImage is best for images with URLs, usually from the Internet, and Haneke is good for ID-based images such as thumbnails created from videos. Both are available at CocoaPods.

SDWebImage uses CoreData SQLite DB to cache URLs. It has no methods for β€œhand make” images, but is popular worldwide in REST applications that download images from the Internet. I use it just published in the AppStore MyHairDressers app. FastCache uses files to cache URLs. But it also looks like SDWebImage, not suitable for caching "hand make" images. Both are well suited for images uploaded by URLs. Haneke can store images by individual identifiers, not just URLs. But, like FastCache, some configuration is required. Here is the code for some configurations:

``

 HNKCacheFormat *cacheFormatThumbnail = [[HNKCache sharedCache] formats][CACHE_FORMAT_THUMBNAIL]; if (cacheFormatThumbnail == nil) { cacheFormatThumbnail = [[HNKCacheFormat alloc] initWithName:CACHE_FORMAT_THUMBNAIL]; cacheFormatThumbnail.size = CGSizeMake(100.0f, 56.0f); cacheFormatThumbnail.scaleMode = HNKScaleModeAspectFit; cacheFormatThumbnail.compressionQuality = 0.5f; cacheFormatThumbnail.diskCapacity = 10 * 1024 * 1024; // 10MB cacheFormatThumbnail.preloadPolicy = HNKPreloadPolicyLastSession; [[HNKCache sharedCache] registerFormat:cacheFormatThumbnail]; } HNKCacheFormat *cacheFormatPhoto = [[HNKCache sharedCache] formats][CACHE_FORMAT_PHOTO]; if (cacheFormatPhoto == nil) { cacheFormatPhoto = [[HNKCacheFormat alloc] initWithName:CACHE_FORMAT_PHOTO]; CGFloat scale = [[UIScreen mainScreen] scale]; cacheFormatPhoto.size = CGSizeMake(1280.0f * scale, 720.0f * scale); cacheFormatPhoto.scaleMode = HNKScaleModeAspectFit; cacheFormatPhoto.compressionQuality = 0.5f; cacheFormatPhoto.diskCapacity = 50 * 1024 * 1024; // 50MB cacheFormatPhoto.preloadPolicy = HNKPreloadPolicyNone; [[HNKCache sharedCache] registerFormat:cacheFormatPhoto]; } 

``

and here is an example of creating cached images (TableViewCell contains a CollectionView with thumbnails):

``

 - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { VideoCell *cell = (VideoCell *)[super tableView:tableView cellForRowAtIndexPath:indexPath]; VideoAsset *asset = (VideoAsset *)[self.fetchedResultsController objectAtIndexPath:indexPath]; if ([asset thumbnails] == 0) { MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:[cell thumbnails]]; hud.removeFromSuperViewOnHide = YES; [[cell thumbnails] addSubview:hud]; hud.labelText = NSLocalizedString(@"H11",nil); [hud show:YES]; CGFloat scale = [[UIScreen mainScreen] scale]; CGSize size = CGSizeMake(100.0f * scale, 56.0f *scale); __weak typeof(cell) weakCell = cell; [asset generateThumbnails:self->thumbnailsCount offset:self->thumbnailsOffset size:size completion:^(NSArray *thumbnails) { dispatch_async(dispatch_get_main_queue(), ^{ [hud hide:YES]; }); if ((thumbnails != nil) && ([thumbnails count] > 0)) { HNKCache *cache = [HNKCache sharedCache]; NSUInteger n = 0; NSUInteger keyHash = [[[asset assetURL] absoluteString] hash]; for (UIImage *image in thumbnails) { [cache setImage:image forKey:[NSString stringWithFormat:@"% lu@ %i",(unsigned long)keyHash,(int)(n++)] formatName:CACHE_FORMAT_THUMBNAIL]; dispatch_async(dispatch_get_main_queue(), ^{ if (weakCell != nil) { __strong typeof(cell) strongCell = weakCell; [[strongCell thumbnails] reloadData]; } }); formatName:CACHE_FORMAT_PHOTO]; } } }]; } return (UITableViewCell *)cell; } 

``

and using (collection collection view cell in table view cell):

``

 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ThumbnailCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; NSString *key = [NSString stringWithFormat:@"% lu@ %i",(unsigned long)[[[(VideoAsset *)self->_selectedObject assetURL] absoluteString] hash],(int)[indexPath item]]; [cell setKey:key]; [cell setTag:[indexPath item]]; __weak typeof(cell) weakCell = cell; [[HNKCache sharedCache] fetchImageForKey:key formatName:CACHE_FORMAT_THUMBNAIL success:^(UIImage *image) { [[weakCell image] setImage:image]; } failure:^(NSError *error) { if ([[error domain] isEqualToString:HNKErrorDomain] && ([error code] == HNKErrorImageNotFound)) { [[weakCell image] setImage:[UIImage imageNamed:@"movieplaceholder"]]; } else [error reportError]; }]; return cell; } 

``

+1
source

Source: https://habr.com/ru/post/1242788/


All Articles