繁体   English   中英

内存用完后,应用程序关闭。 仪器内部屏幕截图

[英]App closes after running out of memory. Instruments screenshot inside

在此处输入图片说明

这是通过仪器运行我的应用程序时得到的。 它正在处理许多核心数据。 我可以看到这显然是不对的,但是我真的不知道该屏幕快照告诉我什么。 似乎是什么问题? 如果您有兴趣,可以使用以下简明代码:

    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

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

在不讨论代码效率的情况下:
在外部循环(while)和内部循环(for)中,将代码包装在@autoreleasepool {}中。
否则,您仅分配大量内存,仅在外部事件循环到达循环结束时才释放它。

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

当然,您确实有很多对象,请考虑优化数据结构。

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

仅查看您发布的代码,就会留下很多问题。

我想查看按总体大小而不是分配数量排序的信息。 这样可以更轻松地告诉您内存的使用位置。 照原样,我看不到该图片在哪里使用了内存(然后,再次出现-旧眼睛-当我放大它时,它变得太模糊了)。

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

继续提供一些诊断帮助。

您的新MOC是直接连接到PSC还是具有父MOC。 如果它具有父MOC,则将保存内容仅推送到父MOC中,并将保留在内存中,直到保存内容保存到数据库中为止。

您的mediaSet中有多少个项目? 可能有很多这样的东西,它们可能会消耗内存。

您已将哪些参数应用于FetchRequest和MOC? 基于这些选项,MOC可以保留对象。 一种检查方法是记录每个MOC的保留/插入/删除/等集的计数。 通过记录这些内容,您可以查看MOC是否正在保留您认为不应该的内容。

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

您可以作弊,然后在保存后调用[moc reset] ,但是最好能在执行前后查看这些数字,以便使自己确信内存在哪里。

进行更多调试。 给自己更多的信息,以便您可以做出明智的决定……这也将为我们提供更好的信息,以帮助您。

编辑

Oooops。 我删除了有关可能内存不足的注释。 我的老眼睛让我看不到那幅图像上的小字。

编辑

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

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

另外,启用核心数据工具。 他们确实提供了很多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM