【问题标题】:Memory Warning on fetching images from device photo library从设备照片库中获取图像的内存警告
【发布时间】:2014-01-19 15:48:48
【问题描述】:

我使用以下代码从照片库中获取图像,在显示之前调整其大小会收到内存警告。 由于内存压力,它也会被终止。

-(void)readImages:(int)getAlbumImages
{

    imagesArray = [[NSMutableArray alloc]init];
    allImagesArray = [[NSMutableArray alloc] init];

    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    void (^assetEnumerator)( ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
        if(result != nil) {
             if([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]) {
                        [allImagesArray addObject:[result valueForProperty:ALAssetPropertyURLs]];

                        NSURL *url= (NSURL*) [[result defaultRepresentation]url];
                        [library assetForURL:url
                                 resultBlock:^(ALAsset *asset) {
                                     [imagesArray addObject:[UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage]]];
                                     [picsTbl reloadData];
                                     [loadingView setHidden:YES];
                                 }
                                failureBlock:^(NSError *error){ NSLog(@"test:Fail"); } ];
                    }

                }
                else if(result == NULL){
                    [loadingView setHidden:YES];
                }
            };

            NSMutableArray *assetGroups = [[NSMutableArray alloc] init];
            void (^ assetGroupEnumerator) ( ALAssetsGroup *, BOOL *)= ^(ALAssetsGroup *group, BOOL *stop) {
                if(group != nil) {
                    [group enumerateAssetsUsingBlock:assetEnumerator];
                    [assetGroups addObject:group];
                    NSLog(@"Number of assets in group :%ld",(long)[group numberOfAssets]);
                    NSLog(@"asset group is:%@",assetGroups);
                }
                NSLog(@"[group numberOfAssets] %d",[group numberOfAssets]);

            };

            assetGroups = [[NSMutableArray alloc] init];

            [library enumerateGroupsWithTypes:ALAssetsGroupAll
                                   usingBlock:assetGroupEnumerator
                                 failureBlock:^(NSError *error) {NSLog(@"A problem occurred");}];
        }

请帮忙。

【问题讨论】:

  • 此代码发布错误的问题
  • 不断收到内存警告。并导致应用终止

标签: ios photolibrary alassetlibrary


【解决方案1】:

很明显,您不能将所有张照片作为全屏图像打开并存储在一个数组中,因为这会导致内存压力并最终导致内存故障,这会导致崩溃。

另外,声明

[picsTbl reloadData];

可能有问题,因为它是系统方法的完成处理程序,因此不清楚它在哪个执行上下文中执行。在这里,如果 picsTbl 是 UITableView 则必须是主线程。您应该确保确实如此。

您需要一种不同的方法来解决您的问题。具体来说,由于您可能正在处理大数据(给定设备受限),您必须确保您只处理 一个 图像,并且一次只将 一个 图像保留在内存中。

您可以了解如何顺序调用异步方法 - 即有效地序列化异步方法,这里:

Force async tasks to run in sequence

ios programming: Using threads to add multiple images to library

【讨论】:

  • 我需要从照片库中获取所有图像并将其显示在视图中。我要先调整图像大小吗?
  • 是的,如果您的原始图像比将要渲染的画布大得多。也就是说,您应该一次处理一张图像,其中处理的结果是下采样图像,在渲染时需要更少的内存。 所有小图像在视图中都显示时必须适合 RAM。但是,如果您的“视图”是表格视图 - 您不需要将所有小图像都放入 RAM,只需要可见的图像即可。有目的地,您将小图像作为“拇指”保存到磁盘,可能保存到一个临时文件夹中。
【解决方案2】:
  • 由于 UIImage 的内存过多而发生崩溃
  • 我们使用了@autorelasePool。
  • 如果您将 imgaes 保存到一个数组中,请在之前调整它的大小 节省。
  • 对于非 ARC

      block = ^(ALAsset *myasset)
    {
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
      // rest of block here
    
      [pool release];     }
    
  • 对于 ARC

    block = ^(ALAsset *myasset)
{
@autoreleasepool{
  // rest of block here

}
}
  • 下面是示例代码

    {

        if(result != nil) 
            if([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]) {
                [assetURLDictionaries addObject:[result valueForProperty:ALAssetPropertyURLs]];
    
                NSURL *url= (NSURL*) [[result defaultRepresentation]url];
    
                [library assetForURL:url
                         resultBlock:^(ALAsset *asset) {
                                 @autoreleasepool {
    
                                     UIImage *imageToSave = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage]];
                                     CGSize sizeToSave = CGSizeMake(30,30);
                                     UIGraphicsBeginImageContextWithOptions(sizeToSave, NO, 0.f);
                                     [imageToSave drawInRect:CGRectMake(0.f, 0.f, sizeToSave.width, sizeToSave.height)];
                                     UIImage *finalImageToSave = UIGraphicsGetImageFromCurrentImageContext();
                                     UIGraphicsEndImageContext();
                                     NSLog(@"mutableArray.count:%d",mutableArray.count);
                                     if (finalImageToSave!=nil) {
                                         [mutableArray addObject:finalImageToSave];
    
                                     }
                                     if ([mutableArray count]==89)//count
                                     {
                                         [imageArray addObjectsFromArray:mutableArray];
                                         [self allPhotosCollected:imageArray];
                                     }
                                 }
                         }
                        failureBlock:^(NSError *error){
                            [[[UIAlertView alloc]initWithTitle:@"" message:@"operation was not successfull!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]show];
                            NSLog(@"operation was not successfull!");
                        } ];
            }
        }else{
    
            //handle UI
        }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-19
    • 2014-03-01
    • 1970-01-01
    • 2021-05-12
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多