【问题标题】:Objective-c UIImagePNGRepresentation causing memory leakObjective-c UIImagePNGRepresentation 导致内存泄漏
【发布时间】:2017-02-20 00:16:20
【问题描述】:

我正在尝试下载一些图像(从 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 包装代码,但没有任何区别。

【问题讨论】:

  • 尝试使用@autoreleasepool 包装您的代码,如下所示:stackoverflow.com/a/9779032/1689376
  • @alex 我已经尝试过了,但没有成功。相应地更新了我的问题。

标签: ios objective-c memory-leaks uiimagepngrepresentation


【解决方案1】:

真正的问题是这一行:

for (UIImage *image in etrackDiagrams.imageArray) {

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

【讨论】:

  • 你的观点很好。我现在所做的是尝试保存从 URL 中检索到的图像(单独)。虽然仍然没有快乐:/
  • 如果图像在检索时保存到磁盘,为什么需要再次将其转换为Png数据?它是数据。它被保存了。它有一条路径。完成。
  • 这是一个 base64 字符串,我将其转换为 png,以便在画廊中使用。
  • 不,我不关注。您现在没有显示任何画廊。您下载的数据是图像数据。说“base64”不会给故事增加任何东西,是吗?这只是意味着你下载了它,我们已经知道了。
  • 让我换一种说法。 for (UIImage *image in etrackDiagrams.imageArray) 这行证明你可以从下载的数据中派生出 UIImage 对象。但是,在数据保存到磁盘后,您可以从下载的数据中派生 UIImage 对象。您无需对 PNG 执行一些中间转换即可重新保存此数据。它已经准备好摇滚了。
【解决方案2】:

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

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);因为图像很大。我觉得这条信息很重要!!!

有人遇到了同样的问题。click here

【讨论】:

    【解决方案3】:

    也许你可以改变主意:

    1. 当您下载base64字符串时,将其转换为nsdata,然后添加到您的数组中;
    2. 当您要保存图像数据时,请选择数组中的 nsdata。

    除非你想在某些视图上显示图像,否则你不需要注意 发生内存警告。

    【讨论】:

      猜你喜欢
      • 2014-10-08
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多