【问题标题】:Memory issue when working with large array of UIImage处理大量 UIImage 时的内存问题
【发布时间】:2016-02-11 15:07:46
【问题描述】:

我在一个数组中存储了大约 100 个UIImage。我知道存在最终导致应用程序崩溃的内存使用问题,特别是在旧设备(iPhone 4s)上。就用户体验而言,将所有 UIImages 存储在 DocumentsDirectory 上 - 不是一种选择(需要太长时间)。所以我在考虑“合并”这两种方法。等到我收到内存使用警告,停止将图像保存到我的阵列,然后开始通过磁盘存储。我找不到正确的方法来处理Memory leak/warning/usage call

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

当我在真实设备上进行测试时,它只是崩溃 - 没有调用该方法。有什么建议吗?

【问题讨论】:

  • 我认为,如果您遇到此类问题,请降低图像质量或让它们等待应用写入磁盘。
  • 嘿@GabrielJones。不幸的是我不能。由于我的应用程序需要,它们应该一起存在。换句话说,我无法将组分开。
  • @GabrielJones,实际上我将质量降低了近 60%(这甚至比我需要的还要少)。一个很好的问题可能是,就质量/字节而言,调整图像大小的最有效方法是什么
  • 看看这个:虽然它在 Obj-c 中...stackoverflow.com/a/7990532/4431068

标签: swift memory memory-management uiimage


【解决方案1】:

尝试使用图像缓存库。 最受欢迎的比较在这里: https://bpoplauschi.wordpress.com/2014/03/21/ios-image-caching-sdwebimage-vs-fastimage/

我的经验:SDWebImage 最适合通常来自互联网的 URL 来源图像,而 Haneke 最适合基于 ID 的图像,例如从视频生成的缩略图。 两者都在 CocoaPods 中可用。

SDWebImage 使用 CoreData SQLite DB 进行 URL 缓存。它没有“手工制作”图像的方法,但在 ~REST 应用程序中流行于从互联网下载图像。我正在使用它刚刚发布在 AppStore MyHairDressers 应用程序中。 FastCache 使用文件进行 URL 缓存。但它也像 SDWebImage 一样不适合缓存“手工制作”图像。两者都非常适合通过 URL 下载的图像。 Haneke 不仅可以通过 URL 来通过自定义 ID 存储图像。但像 FastCache 一样,它需要一些配置。以下是一些配置的代码:

``

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];
        }

``

这里是创建缓存图像的示例(TableViewCell 包含带有缩略图的 CollectionView):

``

- (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;
}

``

并使用(表视图单元格中集合的集合视图单元格):

``

- (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;
}

``

【讨论】:

  • 谢谢,我去看看!
  • SDWebImage 使用 CoreData SQLite DB 进行 URL 缓存。它没有“手工制作”图像的方法,但在 ~REST 应用程序中流行于从互联网下载图像。我正在使用它刚刚发布在 AppStore MyHairDressers 应用程序中。
  • 我知道这对于在线获取非常有用,尽管我使用的是本地创建的图像。我需要让它们保持一些缓存,至少填充缓存并且只有它们存储它们
  • 我在上面的回答中放了一些代码示例,对不起 ObjC,因为“手工制作”而不是互联网来源的图像缓存
  • 感谢 Alexey 提供了非常有用的答案。我会深入研究的!
猜你喜欢
  • 2010-11-28
  • 1970-01-01
  • 2011-06-06
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
  • 2016-03-25
  • 2018-07-03
  • 1970-01-01
相关资源
最近更新 更多