ios - 使用元数据从照片库中获取图像时出现内存问题

标签 ios objective-c iphone

我正在尝试从照片库中获取所有照片以及图像的元数据。它适用于 10-20 张图像,但当图像超过 50 张时,它会占用太多内存,从而导致应用程序崩溃。

为什么我需要将所有图像放入数组中?
答案 - 将图像发送到服务器应用程序。 [我正在使用 GCDAsyncSocket 在接收器套接字/端口上发送数据,并且在套接字/端口上发送图像时,我没有太多的等待时间从 PHAsset 请求图像。

我的代码:

+(void)getPhotosDataFromCamera:(void(^)(NSMutableArray *arrImageData))completionHandler
{
    [PhotosManager checkPhotosPermission:^(bool granted)
    {
        if (granted)
        {
            NSMutableArray *arrImageData = [NSMutableArray new];

        NSArray *arrImages=[[NSArray alloc] init];

        PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];

        NSLog(@"%d",(int)result.count);

        arrImages = [result copy];

        //--- If no images.
        if (arrImages.count <= 0)
        {
            completionHandler(nil);
            return ;
        }

        __block int index = 1;
        __block BOOL isDone = false;
        for (PHAsset *asset in arrImages)
        {
            [PhotosManager requestMetadata:asset withCompletionBlock:^(UIImage *image, NSDictionary *metadata)
             {
                 @autoreleasepool
                 {
                     NSData *imageData = metadata?[PhotosManager addExif:image metaData:metadata]:UIImageJPEGRepresentation(image, 1.0f);

                     if (imageData != nil)
                     {
                         [arrImageData addObject:imageData];
                         NSLog(@"Adding images :%i",index);

                         //--- Done adding all images.
                         if (index == arrImages.count)
                         {
                             isDone = true;
                             NSLog(@"Done adding all images with info!!");
                             completionHandler(arrImageData);
                         }
                         index++;
                     }
                 }
             }];
        }
    }
    else
    {
        completionHandler(nil);
    }
}];
}


typedef void (^PHAssetMetadataBlock)(UIImage *image,NSDictionary *metadata);

+(void)requestMetadata:(PHAsset *)asset withCompletionBlock:(PHAssetMetadataBlock)completionBlock
{
    PHContentEditingInputRequestOptions *editOptions = [[PHContentEditingInputRequestOptions alloc]init];
    editOptions.networkAccessAllowed = YES;
    [asset requestContentEditingInputWithOptions:editOptions completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info)
     {
         CIImage *CGimage = [CIImage imageWithContentsOfURL:contentEditingInput.fullSizeImageURL];
         UIImage *image = contentEditingInput.displaySizeImage;

         dispatch_async(dispatch_get_main_queue(), ^{
             completionBlock(image,CGimage.properties);
         });

         CGimage = nil;
         image = nil;

     }];

    editOptions = nil;
    asset =nil;
}

+ (NSData *)addExif:(UIImage*)toImage metaData:(NSDictionary *)container
{



 NSData *imageData = UIImageJPEGRepresentation(toImage, 1.0f);
       // create an imagesourceref
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) imageData, NULL);

// this is the type of image (e.g., public.jpeg)
CFStringRef UTI = CGImageSourceGetType(source);

// create a new data object and write the new image into it
NSMutableData *dest_data = [[NSMutableData alloc] initWithLength:imageData.length+2000];
CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)dest_data, UTI, 1, NULL);

if (!destination) {
    NSLog(@"Error: Could not create image destination");
}

// add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef) container);
BOOL success = NO;
success = CGImageDestinationFinalize(destination);

if (!success) {
    NSLog(@"Error: Could not create data from image destination");
}

CFRelease(destination);
CFRelease(source);
imageData = nil;
source = nil;
destination = nil;

return dest_data;

}

最佳答案

你遇到这种情况并不奇怪,因为你的每个图像都消耗内存,你实例化它们并将它们保存在内存中。这不是真正正确的设计方法。 最后,这取决于您要对这些图像做什么。

我建议您只保留 PHAsset 对象的数组,并仅在需要时请求图像。 就像如果你想将这些图像表示到 tableView/collectionView 中,执行对

的调用

[PhotosManager requestMetadata:asset withCompletionBlock:^(UIImage *image, NSDictionary *metadata)

直接在特定方法中。这样您就不会耗尽设备内存。

关于ios - 使用元数据从照片库中获取图像时出现内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45207096/

相关文章:

ios - 使用 Mapkit 实现多个覆盖

ios - 如何在 Xcode8 中锁定文件?

objective-c - 在 Objective-C 中获取方法的返回类型的方法?

ios - Swift:无法在自定义 View 上调用 removeFromSuperview()

iphone - Itunes 连接不检测应用程序 ID

ios - 如何替换捆绑文件的内容

ios - 如何在 iOS 应用程序中编辑 PDF 表单?

iphone - 响应 UIScrollView 内以编程方式生成的自定义 UIButton 的触摸

iphone - 如何使用 Quartz Framework 绘制图形

ios - 在 Swift 中使用 commitEditingStyle 动态删除 UITable 部分