Objective c 核心数据内存使用和内存警告

Objective c 核心数据内存使用和内存警告,objective-c,ios,xcode,core-data,memory-management,Objective C,Ios,Xcode,Core Data,Memory Management,我有这个问题。 我有一个核心数据的图像数据库。 我获取所有图像(大约80MB)并放入一个NSMutableArray。 对象出现了正确的故障: NSArray *fetchResults = [self.managedObjectContext executeFetchRequest:request error:&error]; self.cache = [NSMutableArray arrayWithArray:fetchResults]; for (ImageCache *imag

我有这个问题。 我有一个核心数据的图像数据库。 我获取所有图像(大约80MB)并放入一个NSMutableArray。 对象出现了正确的故障:

NSArray *fetchResults = [self.managedObjectContext executeFetchRequest:request error:&error];
self.cache = [NSMutableArray arrayWithArray:fetchResults];
for (ImageCache *imageObject in self.cache) {
    NSLog(@"Is fault? %i", [imageObject isFault]);
}
通过阅读日志,我发现所有对象都出现了正确的故障 然而,使用仪器时,我看到使用了80MB的内存。 我认为这就是核心数据缓存其结果的原因,并且应该在需要时释放内存。 但是(这是我的“问题”),如果我模拟一个内存警告,什么也不会发生! 80MB仍然存在

看看工具分配,80MB被许多Malloc使用:(示例)

图形类别活动字节#活动字节#临时总字节#总字节#分配(净/总) 0 Malloc 176,00 KB 8,59 MB 50 57 18,39 MB 107%0.00,%0.00 0 Malloc 200,00 KB 8,20 MB 42 460 98,05 MB 502%0.00,%0.04 0 Malloc 168,00 KB 7,05 MB 43 19 10,17 MB 62%0.00,%0.00

这是指向整个呼叫树图像的链接:


有什么想法吗?谢谢

我认为你应该批量将较少的对象加载到内存中

coredata释放的内存发生在幕后,您不必为其编程;坏消息是它发生在幕后,因此可以“神奇地”吞噬记忆


围绕它的方式很多;例如,使用谓词仅选择绝对需要的行;不要做一个常规调用来获取所有内容,然后逐个查看列表。当您执行常规调用并且CoreData尝试加载所有对象时,很可能会崩溃。

好的,我已经理解了为什么会发生这种情况。当您对实体发出获取请求时,即使启用了故障处理,该实体的所有数据都将加载到内存中。包括大的二进制数据。 您可以使用多种方法解决此问题:

1-在您的
NSFetchRequest
[请求集包括属性值:否]上设置此选项
设置否,数据不会立即加载到缓存中,而是仅在请求时加载(当您访问属性并触发故障时)
但这有一个“问题”。即使您尝试再次对属性进行故障诊断(因为您不需要立即使用它,并且希望使用
[self.managedObjectContext refreshObject:object mergeChanges:NO];
),也不会释放内存。在重置managedObjectContext之前,缓存保持活动状态

这样更好:

2-您可以将数据拆分为单独的实体。在我的例子中,我只有两个属性:url和图像数据。我将数据拆分为两个具有1:1关系的实体:imagecache和imagedata。 对“imagecache”实体(具有url属性)的所有行发出fetchRequest,并且与前面的解决方案一样,没有缓存内存。Property imagecache.relationship.image出现错误。访问此属性导致触发故障并填充缓存。 但在本例中,执行
[self.managedObjectContext refreshObject:object mergeChanges:NO],导致立即释放缓存和内存,再次导致imagecache.relationship.image属性出错。注意:如果您执行了
[self.managedObjectContext refreshObject:object.relationship mergeChanges:NO]
,则不要对“子”对象执行此操作,因为某些原因缓存未被释放。我想这就是为什么你要穿越这段关系


3-我说这主要是一个学术问题,解决这个问题的真正“全天”解决方案(更好的性能和更少的头痛)是避免将大数据保存在核心数据数据库中。您可以将数据另存为文件并仅存储引用(文件路径),或者使用iOS 5,您可以在核心数据模型内的任何“数据”属性上设置“使用外部存储”。这将为您完成所有工作。

可能核心数据会在
内存警告级别2上释放内存。
?您的场景是否可能产生低内存崩溃?是否有任何“神奇的方法”来模拟内存警告级别2?或者“简单地”我必须消耗内存?我不知道任何模拟方法。您应该运行另一个“重”应用程序(例如Appstore),将您的应用程序保持在后台,并跟踪控制台日志和内存图表。控制台中会出现
2级
警告-所以此时您应该查看内存表。Mmmmhh…但是如果我将应用程序保留在后台,它将被冻结,因此我不会从系统接收消息,不是吗?但是我尝试了别的方法。我做了一个开始浪费内存的循环(一个简单的数据数组)。我尝试了不同数量的内存(尝试了很多次,有时让iOS杀死我的应用程序),但核心数据从未释放缓存:-/(显然是在设备上尝试过,而不是在模拟器上尝试过)嗯…在这个链接上,文档说内存警告不会发送到sospended应用程序:“当系统向应用程序发送内存不足警告时,请立即响应。当可用内存量降至安全阈值以下时,iOS会通知所有正在运行的应用程序。是的,我应用的第一个解决方案是只获取我需要的数据。这主要是一个“学术性的”问题"问题。文档对此很清楚,缓存管理是由核心数据进行的,所有操作都发生在幕后,但它甚至说如果内存不足,内存是可用的。我希望在内存警告后看到核心数据使用的内存减少。没有看到这一点,我认为我的代码中有问题。。。!我希望看到“用我的眼睛”核心数据在内存不足的情况下释放内存:-)只是一个更新:我试图占用内存(分配一些NSData实例的简单循环),但核心数据从未释放内存(我尝试了很多次,分配100MB的NSData,然后是200,然后是300…直到应用程序崩溃)。它似乎缓存了fetchrequest的所有数据,但没有释放它,永远不会!我知道我可以用其他方法来达到我的目标