简体   繁体   English

Objective-C UIImagePNGRepresentation导致内存泄漏

[英]Objective-c UIImagePNGRepresentation causing memory leak

I'm trying to download and save some images (converted from a base64 string to UIImage) to the device and keep getting a Memory warning. 我正在尝试将一些图像(从base64字符串转换为UIImage)下载并保存到设备,并不断收到“内存”警告。

ontracFullScreenImageViewController *etrackDiagrams = ((ontracFullScreenImageViewController*)[viewControllerDictionary objectForKey:@"E-track Diagrams"]);
    NSMutableSet *etrackSet = [[NSMutableSet alloc] init];

    for (UIImage *image in etrackDiagrams.imageArray) {


        NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];
        //convert the image to NSData and store it in the documents directory
        NSData *pngData = UIImagePNGRepresentation(image);
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
        NSString * timeInMS = [NSString stringWithFormat:@"%lld", [@(floor([[NSDate date] timeIntervalSince1970] * 1000)) longLongValue]];
        NSString *filePath = [documentsPath stringByAppendingPathComponent:[ NSString stringWithFormat:@"%@_%@_etrack_diagram_%i_%i_image.png", delegate.userName, timeInMS, self.dataObject.dataPack.pack_id, [etrackDiagrams.imageViewArray indexOfObject:image]]]; //Add the file name
        [pngData writeToFile:filePath atomically:YES];
        NSLog(@"filepath %@", filePath);
        NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
        if ([currSysVer isEqualToString:@"5.0.1"]) {
            [[NSURL URLWithString:filePath] setResourceValue: [NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: &error];
        }
        //Add the file Path to ImageLinks
        [etrackDiagrams.imageLinks addObject:filePath];
        //save the image location in Core Data
        EtrackDiagram *etrackDiagram = [NSEntityDescription
                                        insertNewObjectForEntityForName:@"EtrackDiagram"
                                        inManagedObjectContext:context];
        etrackDiagram.locationString = filePath;
        etrackDiagram.dataObject = dataObject;
        [etrackSet addObject:etrackDiagram];
        [dataObject addEtrackDiagramsObject:etrackDiagram];
        [localPool drain];

    }
    [dataObject addEtrackDiagrams: etrackSet];

The memory warning occurs at NSData *pngData = UIImagePNGRepresentation(image); 内存警告发生在NSData *pngData = UIImagePNGRepresentation(image); as the images are quite large. 因为图像很大。

Unfortunately I can't control the size of the images but need a way to save them to the device to use them in a gallery later on. 不幸的是,我无法控制图像的大小,但是需要一种将它们保存到设备中的方法,以便以后在图库中使用它们。

I have tried to wrap the code with @autoreleasepool but it made no difference. 我试图用@autoreleasepool包装代码,但没有区别。

The real problem is this line: 真正的问题是这一行:

for (UIImage *image in etrackDiagrams.imageArray) {

This implies you are holding an array of images in memory. 这意味着您正在将一系列图像保存在内存中。 That is always dangerous. 那总是很危险的。 You need to have saved all these images on disk and load them into memory one at a time (and in a noncaching way). 您需要将所有这些映像保存在磁盘上,然后一次(以非缓存方式)将它们一次加载到内存中。 Your goal should be to have at most one image in memory at a time. 您的目标应该是一次最多存储一个图像。

here is the code to prove matt's theory was wrong. 这是证明马特理论是错误的代码。

for(NSInteger i =0; i < etrackDiagrams.imageArray.count; i ++) {
   UIImage *image = etrackDiagrams.imageArray[i];
   // here is your code to save image in device.
}

if "for(uiimage *image in imagearray)" holding an array of images in memory, then the code above will fix the problem, but in fact, it's basically without any help. 如果“ for(uiimage * imagearray中的图像)”在内存中保存图像数组,则上面的代码将解决该问题,但实际上,它基本上没有任何帮助。

The memory warning occurs at NSData *pngData = UIImagePNGRepresentation(image); 内存警告发生在NSData * pngData = UIImagePNGRepresentation(image); as the images are quite large. 因为图像很大。 I think this message is very important!!! 我认为此消息非常重要!!!

here is someone had the same problem. 这是有人遇到同样的问题。 click here 点击这里

Maybe you can change a mind: 也许您可以改变主意:

  1. when you download the base64 string, convert it into nsdata, then add to your array; 当您下载base64字符串时,将其转换为nsdata,然后添加到您的数组中;
  2. when you want to save the imagedata, select the nsdata in your array. 当您要保存图像数据时,请在阵列中选择nsdata。

unless you want show the image on some views, you don't need to pay attention to the memory warning occurs. 除非您想在某些视图上显示图像,否则无需注意发生内存警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM