应用程序在耗尽内存后关闭。仪器截图里面

时间:2012-09-17 12:05:02

标签: iphone objective-c ios core-data core-data-migration

enter image description here

这是我通过乐器运行应用程序时得到的结果。它正在处理大量核心数据。我可以看到这显然是不对的,但我真的不知道这个截图告诉我的是什么。似乎是什么问题?如果您感兴趣,那么缩小的代码就是:

    NSFetchRequest *oldFetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *oldEntryEntity = [NSEntityDescription entityForName:@"Entry"
                                                      inManagedObjectContext:oldContext];

    [oldFetchRequest setEntity:oldEntryEntity];

    int numberOfEntries = [oldContext countForFetchRequest:oldFetchRequest error:nil];

    int batchSize = 4;
    [oldFetchRequest setFetchLimit:batchSize];
    int offset = 0;

    while (numberOfEntries - offset > 0) {
        @autoreleasepool {
        [oldFetchRequest setFetchOffset:offset];
        NSError *error;
        NSArray *entries = [oldContext executeFetchRequest:oldFetchRequest error:&error];

        for (NSManagedObject *entry in entries) {
        @autoreleasepool {
            Entry *newEntry = [NSEntityDescription insertNewObjectForEntityForName:@"Entry"
                                                            inManagedObjectContext:newContext];

            newEntry.entryID = [entry valueForKey:@"entryID"];

            NSMutableOrderedSet *newMediaSet = [[NSMutableOrderedSet alloc] init];

            NSOrderedSet *mediaSet = [entry valueForKey:@"media"];

            int i = 0;

            for (NSManagedObject *media in mediaSet) {

                Media *newMedia = [NSEntityDescription insertNewObjectForEntityForName:@"Media"
                                                                inManagedObjectContext:newContext];

                newMedia.isInPhotoLibrary = [media valueForKey:@"isInPhotoLibrary"];
                newMedia.positionInEntry = [NSNumber numberWithDouble:i + 1];

                MediaImageData *imageData = [NSEntityDescription insertNewObjectForEntityForName:@"MediaImageData"
                                                                          inManagedObjectContext:newContext];

                imageData.data = [media valueForKey:@"originalImage"];

                newMedia.imageData = imageData;

                newMedia.entry = newEntry;
                [newMediaSet addObject:newMedia];

                i++;
            }

            newEntry.media = newMediaSet;


        }
        }

        [newContext save:&error];

        offset = offset + batchSize;
   }
}
编辑:我按照这里给出的建议,将它包装在@autoreleasepools(我已在上面编辑过)中,并且在发生这种情况后它仍然崩溃:

http://cl.ly/image/1U2T2p3w1X2Z

它显然比第一次进入代码,但它仍然崩溃。

3 个答案:

答案 0 :(得分:2)

不讨论代码的效率:
将您的代码包含在@autoreleasepool {}中,用于外部(while)和内部(for)循环 否则,你只需要分配大量内存并在外部事件循环到达循环结束时释放它。

答案 1 :(得分:1)

尝试在for中包装快速枚举(@autoreleasepool循环)的内部,这应该会有所帮助。当更改达到危险的内存消耗时,您还可以运行某种计数器来保存环路中的上下文。

你确实有很多对象,考虑优化数据结构。

答案 2 :(得分:1)

首先,就发布核心数据相关问题提出一些建议。几乎没有太多信息。当您省略细节时,人们很难帮助您,因为有太多可能的互动。

只要查看您发布的代码,就会留下太多问题。

我希望看到按整体大小排序的信息,而不是分配数量。这将更容易告诉你内存的使用位置。事实上,我无法看到那张照片中的内存使用位置(然后再次 - 老眼睛 - 当我放大它时,它会变得太模糊)。

如果您认为它与核心数据有关,为什么不运行核心数据工具?

接受一些诊断帮助。

您的新MOC是直接连接到PSC还是拥有父MOC?如果它有父MOC,则保存只会被推送到父MOC中,并且将保留在内存中,直到保存持久存储到数据库。

您的mediaSet中有多少项?它可能有很多可能会扼杀记忆的东西。

您将哪些参数应用于FetchRequest和MOC?根据这些选项,MOC可以保留对象。检查这一点的方法是记录每个MOC的保留/插入/删除/等设置的计数。通过记录这些,您可以看到MOC是否持有您认为不应该存在的东西。

然后您就可以知道是否需要刷新/重置MOC。

你可以作弊,并在保存后调用[moc reset],但是在这之前/之后看到数字会很好,这样你就可以说服自己记忆的位置。

做更多调试。给自己更多的信息,这样你就可以做出正确的决定......它也会为我们提供更好的信息来帮助你。

修改

Oooops。我删除了关于可能没有太多内存的评论。我的老眼睛没有看到那张图片上的小字体。

修改

  

感谢。如何记录保留/插入/删除的集的计数   对于每个MOC? - 安德鲁

MOC有几个属性(registeredObjectsinsertedObjectsdeletedObjectsupdatedObjects),提供一组与这些类别匹配的对象。只需NSLog每个类别中对象的数量。对于每个MOC,您可以看到MOC随时间跟踪的对象数量。

此外,启用核心数据工具。它们确实非常有用。