Ios CoreData-内存-多个NSManagedObjectContext-由于内存压力而终止
问题:运行约30-60分钟后,由于内存压力,我的应用程序终止 注意事项:此应用程序是一个概念验证应用程序,永远不会出现在应用程序商店中。它是通过HockeyApp分发的,因此可以(如有必要)使用funkyapi调用 我正在寻求关于以下事项的一些建议:Ios CoreData-内存-多个NSManagedObjectContext-由于内存压力而终止,ios,iphone,ipad,core-data,Ios,Iphone,Ipad,Core Data,问题:运行约30-60分钟后,由于内存压力,我的应用程序终止 注意事项:此应用程序是一个概念验证应用程序,永远不会出现在应用程序商店中。它是通过HockeyApp分发的,因此可以(如有必要)使用funkyapi调用 我正在寻求关于以下事项的一些建议: 我需要更改我的数据模型吗 我的数据逻辑是否存在致命缺陷 我的核心数据设置如下所示: 实体:FlightRecording[与AHRSMessage的一对多关系] 实体:AHRSMessage[与FlightRecording的多对一关系] 我使用的
FlightRecording
[与AHRSMessage的一对多关系
]
实体:AHRSMessage
[与FlightRecording的多对一关系
]
我使用的是一个非车载wifi设备,它可以发出信息(大约每秒13-20条),这些信息由我的应用程序中的后台线程捕获
核心数据设置
- 单亲NSManagedObjectContext:
NSMainQueueConcurrencyType
- 多个子NSManagedObjectContext:
NSPrivateQueueConcurrencyType
NSMainQueueConcurrencyType
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
并在初始化调用中传递到后台类。然后从这个主上下文派生出一个子上下文来处理大量的数据写入
子上下文用于处理大部分数据收集。在某些时候,会将子上下文写入父上下文,并使用以下函数创建新上下文:
if (msgCount % 50 == 0) {
// Child Save!
NSLog(@"Saving SDatas");
__block NSManagedObjectContext *currentChild = [self getChildContext];
[self incChildContext];
// Parent-Child save methodology
[currentChild performBlock:^{
NSError *error;
if (![currentChild save:&error]) {
abort();
}
[parentObjectContext performBlock:^{
NSError *error;
if (![parentObjectContext save:&error]) {abort();}
}];
[currentChild reset];
}];
}
因为这段代码发生在一个performBlock中,所以可能会继续接收消息,因此为了不让应用程序崩溃,我在保存“当前”上下文之前,会立即创建一个新的childContext。在创建一个新的上下文时,我检查数组,看看是否可以删除数组中的第一个上下文。实际上,一次只有两个子上下文在浮动
正如我所说,这个应用程序永远不会进入AppStore,我编写了一个函数,允许我从NSManagedObjectContext访问私有变量\u unprocessedInserts
//Add a new child context and potentially remove empty child context form array
- (void)incChildContext {
if (
((NSManagedObjectContext *)[childContextArray firstObject]).getUnprocessedInserts == 0) {
NSLog(@"Empty First");
[childContextArray removeObjectAtIndex:0];
}
[childContextArray addObject:[self makeNewChildContext]];
}
//MAKE NEW CHILD CONTEXT
- (NSManagedObjectContext*)makeNewChildContext {
NSManagedObjectContext *newChild = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[newChild setParentContext:parentObjectContext];
if (currentRecordingID != nil) { // Pass the recordingObject across contexts
[newChild objectWithID:currentRecordingID];
}
return newChild;
}
- (NSManagedObjectContext*)makeNewChildContext {
NSManagedObjectContext *newChild = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[newChild setParentContext:parentObjectContext];
if (currentRecordingID != nil) {
[newChild objectWithID:currentRecordingID];
}
return newChild;
}
所以,一切都很好,运行得很好,但最终我们的内存开始耗尽。从使用仪器来看,AHRSMessages似乎永远不会离开内存事件,尽管我调用了[currentChild reset]
,我认为这会使所有消息无效或诸如此类
这个设置是否有内在的错误
有没有可能因为航班和消息之间的一对多关系,消息永远不会失效并保存在内存中,直到我处理完航班对象?在这种情况下,有没有关于如何避免内存耗尽的建议
谢谢 关系很难实现,因为一旦实现了关系,它们就可以在内存中保存许多对象,直到关系失效为止(通过使用
refreshObject:mergeChanges:
刷新对象)。另外,您确定这些AHRSMessages
对象来自子上下文而不是主上下文吗?我在子上下文->中创建它们,但我相信当我保存它们时,它们会被推到主上下文否?[有没有办法通过查看对象来验证这一点?它是否持有指向正确上下文的指针?]每个上下文都有自己的托管对象。它们不会从一个上下文传递到另一个上下文。释放上下文后,其对象也将被释放。重置上下文不会释放对象,只会将它们变成错误,但会保留一些最小的数据。通过检查对象的managedObjectContext
方法,可以找到对象的上下文。如果由于内存压力而终止,应用程序会如何响应内存警告?Instruments中的分配模板告诉您应用程序是如何分配内存的?