Objective-c UIImagePNGRepresentation导致内存泄漏

时间:2016-10-11 12:43:27

标签: ios objective-c memory-leaks uiimagepngrepresentation

我正在尝试下载并保存一些图像(从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];

内存警告发生在NSData *pngData = UIImagePNGRepresentation(image);,因为图像非常大。

不幸的是,我无法控制图像的大小,但需要一种方法将它们保存到设备中,以便以后在图库中使用它们。

我试图用@autoreleasepool包装代码,但没有区别。

3 个答案:

答案 0 :(得分:1)

真正的问题是这一行:

for (UIImage *image in etrackDiagrams.imageArray) {

这意味着您在内存中保存了一系列图像。这总是危险的。您需要将所有这些图像保存在磁盘上并一次一个地加载到内存中(并以非缓存方式)。您的目标应该是一次在内存中最多只有一个图像。

答案 1 :(得分:0)

这是证明亚特理论错误的代码。

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

如果“for(uiimage * image in imagearray)”在内存中保存一组图像,那么上面的代码将解决问题,但事实上,它基本上没有任何帮助。

内存警告发生在NSData * pngData = UIImagePNGRepresentation(image);因为图像非常大。我认为这个消息非常重要!!!

这里有人有同样的问题。here

答案 2 :(得分:0)

也许你可以改变主意:

  1. 下载base64字符串时,将其转换为nsdata,然后添加到您的数组中;
  2. 如果要保存图像数据,请在阵列中选择nsdata。
  3. 除非你想在某些视图上显示图像,否则你不需要注意  发生内存警告。