这是一个小背景:
我在Core Data中存储了相当大的图像(900x1200像素)。它们来自UIImagePickerView,我将它们裁剪并调整为合理的大小。
我正在使用一个非常标准的值转换器来转换UIImage和NSData(并返回。)
该程序有效,但最终会收到内存警告,然后终止。
如果删除将图像写入Core Data的行,则问题就会消失(但我需要存储这些图像!)
当我运行Instruments时,“分配”会在图像选择器返回全分辨率图像时显示预期的峰值,并将其调整大小。转换完成后,我从5转到约22兆,然后回到5。
分配从未显示出任何增长。
我有一个大约200字节的泄漏,我几乎是积极的无关,但我在完全披露中提到它。
现在,当我使用Memory Monitor仪器时,我发现每次保存其中一个图像时,我的应用程序的“真实内存”增长了5兆。
所以,非常感谢任何帮助(或想法)!
为什么分配没有显示出这种增长,但内存监视器呢?这是一个线索吗?
起初我以为是因为我的价值转换器使用的自动释放池可能没有耗尽,但后来我意识到这是我读取数据时,而不是写入数据。
这是相关的代码。如果您对我如何调试这个有任何想法,请告诉我!
-Pete
这是我的价值转换器: 首先是接口声明:
@interface ImageToDataTransformer : NSValueTransformer { }
@end
现在实施:
@implementation ImageToDataTransformer
+ (BOOL)allowsReverseTransformation {
return YES;
}
+ (Class)transformedValueClass {
return [NSData class];
}
- (id)transformedValue:(id)value {
NSData *data = UIImagePNGRepresentation(value);
return data;
}
- (id)reverseTransformedValue:(id)value {
UIImage *uiImage = [[UIImage alloc] initWithData:value];
return [uiImage autorelease];
}
这是我写出来的代码:
FieldCollectorAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSError *error;
NSManagedObject *theFieldObject=nil;
// Populate the bare necessities
theFieldObject = [NSEntityDescription insertNewObjectForEntityForName:@"FieldObject"
inManagedObjectContext:context];
NSManagedObject *theImageObject =[NSEntityDescription insertNewObjectForEntityForName:@"ImageObject" inManagedObjectContext:context];
// Let's link up the two
[theImageObject setValue:theFieldObject forKey:@"fieldObject"];
[theFieldObject setValue:theImageObject forKey:@"photo"];
[theFieldObject setValue:image forKeyPath:@"photo.Photo"];
// Save the context
[context save:&error];
答案 0 :(得分:4)
它无法解决这个谜团,但可以解决您的问题(除非您有某种理由绝对要求以这种方式使用Core Data),但您不应该使用Core Data。它只是不是为了存储如此庞大的二进制数据块而设计的。而是在Core Data中存储对数据(即文件名或URL)的引用,并使用NSData
的{{1}}和dataWithContentsOfFile
。
答案 1 :(得分:2)
问题在于Core Data为了性能而缓存了很多。我应该早些时候猜到这一点,因为我已经编写了类似的通用数据存储算法。它也解释了为什么我没有看到它被分配为我的记忆。将保存消息发送到托管对象上下文时,写入的数据将被缓存。
您可以使用NSManagedObjectContext消息“RefreshObject:mergeChanges:”将NSManagedObjects标记为“脏”(故障)。在发送保存消息的上下文后,直接对该对象执行此操作。
通过使用“NO”作为第二个参数,您说,“您需要返回磁盘才能获得它。”
poof ,解决了我的内存使用问题。
当修复是一行代码时,你不喜欢它吗?
-Pete