问题:运行约30-60分钟后,我的应用程序因内存压力而终止。
需要注意的事项:此应用程序是概念证明应用程序,永远不会出现在App-Store中。它通过HockeyApp分发,因此可以(如有必要)使用时髦的API调用
我正在寻找有关以下事项的一些建议:
我的核心数据设置如下:
实体: FlightRecording
[与AHRSMessage
的一对多关系
实体: AHRSMessage
[与FlightRecording
的多对一关系]
我正在使用一个外接wifi设备,它会在我的应用程序中使用后台线程捕获消息(大约每秒13-20秒)。
核心数据设置
NSMainQueueConcurrencyType
NSPrivateQueueConcurrencyType
我正在为我的“前台线程”使用单个父NSManagedObjectContext。此上下文在ApplicationDelegate中使用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访问私有变量_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]
我认为它应该使所有消息无效或类似的东西。
这个设置有什么固有的错误吗?
由于我与Flight和Message之间的一对多关系,是否有可能消息永远不会失效并保留在内存中,直到我完成飞行对象为止?有关如何避免在这种情况下耗尽内存的任何建议?
谢谢!