Objective-c UIImagePNGRepresentation 导致内存泄漏
Objective-c UIImagePNGRepresentation causing memory leak
我正在尝试下载并保存一些图像(从 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
包装代码,但没有任何区别。
真正的问题是这一行:
for (UIImage *image in etrackDiagrams.imageArray) {
这意味着您在内存中保存了一组图像。那总是很危险的。您需要将所有这些图像保存在磁盘上并一次将它们加载到内存中(并且以非缓存方式)。您的目标应该是一次最多在内存中保存一张图像。
这里是证明马特理论错误的代码。
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
也许你可以改变主意:
- 下载 base64 字符串时,将其转换为 nsdata,然后添加到数组中;
- 当您想保存图像数据时,select 数组中的 nsdata。
除非你想在某些视图上显示图像,否则你不需要关注
出现内存警告。
我正在尝试下载并保存一些图像(从 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
包装代码,但没有任何区别。
真正的问题是这一行:
for (UIImage *image in etrackDiagrams.imageArray) {
这意味着您在内存中保存了一组图像。那总是很危险的。您需要将所有这些图像保存在磁盘上并一次将它们加载到内存中(并且以非缓存方式)。您的目标应该是一次最多在内存中保存一张图像。
这里是证明马特理论错误的代码。
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
也许你可以改变主意:
- 下载 base64 字符串时,将其转换为 nsdata,然后添加到数组中;
- 当您想保存图像数据时,select 数组中的 nsdata。
除非你想在某些视图上显示图像,否则你不需要关注 出现内存警告。