【问题标题】:ARC not freeing original asset after CGCreateWithImageInRect?在 CGCreateWithImageInRect 之后,ARC 没有释放原始资产?
【发布时间】:2012-05-03 04:29:26
【问题描述】:

高级摘要: 我想用更高质量的版本替换相当低分辨率的 ALAsset 组图像 [group posterImage],以便它们可以在屏幕上显示得更大。通常我会根据界面的需要加载它们,但是 [ALAssetsGroup enumerateAssetsAtIndexes] 非常慢。 (我可以预加载比可见的 x 量更宽,并且可能仍然这样做,但这似乎比它的价值更麻烦,并且仍然受到响应缓慢的影响,尤其是在 iOS5 中)

我认为我可以做的是请求每个组中的第一个资产,然后对其进行缩放,存储结果。然而,即使考虑到更大尺寸的图像,我对正在发生的内存分配感到惊讶。使用 VM Tracker,我看到大量 CGImage 分配以及我正在创建的“映射文件”缩略图。我正在使用 ARC,所以我预计原始大图像会丢失,但我的 VM Tracker 结果并没有显示出来。

如果我使用默认的 posterImage 实现,我的 Resident Mem ~= 30mb、Dirty Mem ~= 80mb 和 Virtual tops ~240mb(本身就很大)。 'Live'

如果我改用下面的代码,我会在加载 150 个图像中的第 80 个图像时崩溃。那时我的 Resident Mem > 480mb,Dirty Mem > 420mb,而 Virtual 则高达 750mb。显然这是站不住脚的。

这是我在 NSOperationQueue 中使用的代码,用于抓取每个组的第一张图片以用作高分辨率海报图片。

NSIndexSet* i = [NSIndexSet indexSetWithIndex:0];
ALAssetsGroupEnumerationResultsBlock assetsEnumerationBlock = ^(ALAsset *result, NSUInteger i, BOOL *stop) {

  if (result) {
     // pull the full resolution image and then scale it to fit our desired area
     ALAssetRepresentation *assetRepresentation = [result defaultRepresentation];
     CGImageRef ref = [assetRepresentation fullScreenImage];
     CGFloat imgWidth = CGImageGetWidth(ref);
     CGFloat imgHeight = CGImageGetHeight(ref);
     CGFloat minDimension = MIN(imgWidth,imgHeight);

     // grab a square subset of the image, centered, to use
     CGRect subRect = CGRectMake(0, 0, minDimension, minDimension);
     subRect.origin = CGPointMake(imgWidth / 2 - minDimension / 2, imgHeight / 2 - minDimension / 2);
     CGImageRef squareRef = CGImageCreateWithImageInRect(ref,subRect);
     // now scale it down to fit
     CGFloat heightScale = dimension / minDimension;
     UIImage* coverImage = [UIImage imageWithCGImage:squareRef scale:1/heightScale orientation:UIImageOrientationUp];

     if (coverImage) {
        [mainViewController performSelectorOnMainThread:@selector(imageDidLoad:) 
                                             withObject:[NSArray arrayWithObjects:coverImage, [NSNumber numberWithInt:photoIndex], nil] 
                                          waitUntilDone:NO];
     }      
     CGImageRelease(squareRef);
     // DO NOT RELEASE 'ref' it will be 'zombied' as it is already handled by the system
     //CGImageRelease(ref);

     *stop = YES;
   }
   else {
      // default image grab....
   }
};
[group enumerateAssetsAtIndexes:i options:NSEnumerationConcurrent usingBlock:assetsEnumerationBlock];

我是不是在上面做错了什么,或者我只是不聪明地加载了所有的图像?我想得越多,我就越认为加载可见图像窗口加上它周围的缓冲区是要走的路,但我想了解更多关于我可能在上面的代码中做错了什么。 谢谢!

【问题讨论】:

    标签: ios ios5 nsoperationqueue cgimage alassetslibrary


    【解决方案1】:

    我做了和你完全相同的事情,但感谢这个答案:Fetching the last image captured through iPhone camera,我设法让它更快,并且没有消耗太多内存。

    这当然会使图像更小,因为您不获取 fullScreenImage 而只是它的缩略图..

    我的最终代码:

       ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    
    // Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
    [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
    
        // Within the group enumeration block, filter to enumerate just photos.
        [group setAssetsFilter:[ALAssetsFilter allPhotos]];
        int nrOfPhotos = 200;
        [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, nrOfPhotos)]
                                options:0
                             usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {
    
                                 // The end of the enumeration is signaled by asset == nil.
                                 if (alAsset) {
                                     NSLog(@"Index: %i", index);
    
                                     CGImageRef imageRef = [alAsset thumbnail];
                                     UIImage *latestPhoto = [UIImage imageWithCGImage:imageRef scale:1.f orientation:UIImageOrientationUp];
    
                                     //Do something with images
    
                             }
                             }];
    }
                         failureBlock: ^(NSError *error) {
                             // Typically you should handle an error more gracefully than this.
                             NSLog(@"No groups");
                         }];
    

    【讨论】:

      猜你喜欢
      • 2014-02-19
      • 2013-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多