CoreData - 内存 - 多个NSManagedObjectContexts - 由于内存压力而终止

时间:2014-08-16 11:19:55

标签: ios iphone ipad core-data

问题:运行约30-60分钟后,我的应用程序因内存压力而终止。

需要注意的事项:此应用程序是概念证明应用程序,永远不会出现在App-Store中。它通过HockeyApp分发,因此可以(如有必要)使用时髦的API调用

我正在寻找有关以下事项的一些建议:

  1. 我是否需要更改数据模型
  2. 我的数据逻辑中是否存在致命缺陷
  3. 我的核心数据设置如下:

    实体: FlightRecording [与AHRSMessage的一对多关系

    实体: AHRSMessage [与FlightRecording的多对一关系]

    我正在使用一个外接wifi设备,它会在我的应用程序中使用后台线程捕获消息(大约每秒13-20秒)。

    核心数据设置

    • 单亲NSManagedObjectContext:NSMainQueueConcurrencyType
    • 多个子NSManagedObjectContext: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;
    }
    

    所以一切都很好,花花公子,它运行得很好,但最终我们开始耗尽内存。从使用工具看起来AHR​​SMessages永远不会出现内存事件,而我正在调用[currentChild reset]我认为它应该使所有消息无效或类似的东西。

    这个设置有什么固有的错误吗?

    由于我与Flight和Message之间的一对多关系,是否有可能消息永远不会失效并保留在内存中,直到我完成飞行对象为止?有关如何避免在这种情况下耗尽内存的任何建议?

    谢谢!

0 个答案:

没有答案