5

I'm storing about 100 UIImage at one single array. I know there is a memory usage issue that eventually crashes the app, specifically on older devices(iPhone 4s). In terms of User Experience storing all the UIImages on DocumentsDirectory - is not an option(takes too long). So i was thinking about "merging" this two methods. Wait until i'll receive a memory usage warning,stop saving images to my array, and then start storing over the disk. I can't find the right way to handle Memory leak/warning/usage call

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

When i'm testing on real device, it's just crashes - without call the method. Any suggestions?

13
  • 1
    I think, if you're having issues like this, either reduce the quality of your images or make them wait for the app to write to the disk. Commented Feb 11, 2016 at 15:12
  • Hey @GabrielJones. Unfortunately i can't. Due to my app needs, all of them should exists together. I cant separate the group in other words. Commented Feb 11, 2016 at 15:14
  • @GabrielJones, and actually i reduced the quality by almost 60%(which is even less than what i need). A good question might be, what is the most effective way to resize an image, in terms of quality/bytes Commented Feb 11, 2016 at 15:16
  • Take a look at this: it's in Obj-c though...stackoverflow.com/a/7990532/4431068 Commented Feb 11, 2016 at 15:20
  • 1
    Also look at this: stackoverflow.com/q/29794281/4431068 Commented Feb 11, 2016 at 15:22

1 Answer 1

1

Try to use image cache library. The comparison of the most popular is here: https://bpoplauschi.wordpress.com/2014/03/21/ios-image-caching-sdwebimage-vs-fastimage/

My experience: SDWebImage is the best for URL-sourced images usually from internet and Haneke is good for ID-based images for example thumbnails generated from video. Both available in CocoaPods.

SDWebImage uses CoreData SQLite DB for URL caching. It hasn't methods for "hand make" images but worldwide popular in ~REST applications downloading images from internet. I'm using it in just published in the AppStore MyHairDressers app. FastCache uses files for URL caching. But it also like SDWebImage not suited to cache "hand make" images. Both well suited for images downloaded by URLs. Haneke can store images by custom IDs not only by URLs. But like FastCache it requires some configuration. Here is 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 example for creating cached images (TableViewCell contains 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 view cell of the collection in the 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;
}

``

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, i'll check it!
SDWebImage uses CoreData SQLite DB for URL caching. It hasn't methods for "hand make" images but worldwide popular in ~REST applications downloading images from internet. I'm using it in just published in the AppStore MyHairDressers app.
I know it's very useful for online fetch, tho i'm using local created images..And i need to keep them some how over cache, at at least fill the cache and only them store them
I've put above in my answer some code example, sorry on ObjC, for "hand make" not internet -sourced images cache
Thanks Alexey for a very useful answer. I'll look deep into it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.