核心数据性能 - 在获取和保存对象时大量使用内存

时间:2014-09-13 14:40:25

标签: objective-c core-data memory-leaks nstableview

我为OS X制作了一个应用程序,我面临着一个很大的内存问题,我试图解决这个问题几天没有成功。该应用程序是一个粘贴板管理器,它记录所有项目并在NSTableView中显示它们。 TableView的Controller实现了两个协议NSTableViewDataSource和NSTableViewDelegate来显示TableCells。我没有使用NSArrayController和Interface绑定。

到目前为止,该应用程序在15 MB以下的内存下运行良好。但现在我想用Core Data保留所有项目,以便在用户启动应用程序时加载项目。它也有效,但内存占用超过200 MB。我知道这对于这样的应用来说太过分了。

我刚刚在OS X Yosemite测试版上创建了具有XCode 6 beta核心数据应用模板的应用。我尝试使用Xcode工具来查找错误,但作为新手,这对我帮助不大。我已经阅读了有关Core Data Performance的文档,并尝试将ManagedObjectContext的Undo Manager设置为nil,但这会带来无意义。

以下片段代码显示了我如何使用Core Data存储和加载记录。我希望有一些帮助或建议来减少我的应用程序的内存使用量。

- (instancetype)init
{
    self = [super init];
    if (self) {
        _savedItems = [[NSMutableArray alloc] init];

        /* Core Data - load items */
        AppDelegate *appDelegate = (AppDelegate *) [[NSApplication sharedApplication] delegate];
        NSManagedObjectContext *context = [appDelegate managedObjectContext];
        NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"PasteboardItem" inManagedObjectContext:context];
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        [request setEntity:entityDesc];

        NSError *error;
        NSArray *storedObjects = [context executeFetchRequest:request error:&error];
        [_savedItems addObjectsFromArray:storedObjects];
        /* Core Data End */

        _pasteBoard = [NSPasteboard generalPasteboard];
        changesCount = (int)[_pasteBoard changeCount];
        [self startFetchPasteBoardItemsTimer];
    }
    return self;
}


- (void)fetchNewPasteboardItem {
    PasteboardItem *newPbItem = [self buildPbItemFromPasteBoard:_pasteBoard];
    if ([_savedItems containsObject:newPbItem]) {
        return;
    }

    NSRunningApplication *sourceApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
    NSImage *sourceImage = [sourceApp icon];

    [newPbItem setSourceAppImage:sourceImage];


    /* Core Data - Persist new item */

    AppDelegate *appDelegate = (AppDelegate *) [[NSApplication sharedApplication] delegate];
    NSManagedObjectContext *context = [appDelegate managedObjectContext];

    NSManagedObject *newPasteboardItem;
    newPasteboardItem = [NSEntityDescription insertNewObjectForEntityForName:@"PasteboardItem" inManagedObjectContext:context];

    [newPasteboardItem setValue:newPbItem.stringValue forKeyPath:@"stringValue"];
    [newPasteboardItem setValue:newPbItem.rtfData forKeyPath:@"rtfData"];
    [newPasteboardItem setValue:newPbItem.pdfData forKeyPath:@"pdfData"];
    [newPasteboardItem setValue:newPbItem.filenames forKeyPath:@"filenames"];
    [newPasteboardItem setValue:newPbItem.url forKeyPath:@"url"];
    [newPasteboardItem setValue:newPbItem.contentImage forKeyPath:@"contentImage"];
    [newPasteboardItem setValue:newPbItem.imageInfo forKeyPath:@"imageInfo"];
    [newPasteboardItem setValue:newPbItem.sourceAppImage forKeyPath:@"sourceAppImage"];
    [newPasteboardItem setValue:newPbItem.createdDate forKeyPath:@"createdDate"];
    [newPasteboardItem setValue:newPbItem.lastUsedDate forKeyPath:@"lastUsedDate"];
    [newPasteboardItem setValue:newPbItem.overview forKeyPath:@"overview"];
    [newPasteboardItem setValue:newPbItem.mainText forKeyPath:@"mainText"];

    NSError *error;
    [context save:&error];

    /* Core Data - End of Persistence */

    [_savedItems insertObject:newPbItem atIndex:0];
    [self updateLastItemTimestamp];
}

使用乐器增加内存的两个屏幕截图。

http://i.stack.imgur.com/zFsMG.png

http://i.stack.imgur.com/aES9I.png

1 个答案:

答案 0 :(得分:1)

您正在使用NSXMLStoreType persistent store,这是一种原子商店。这意味着当实例化存储并将其添加到持久性存储协调器时,整个对象图将加载到内存中。这就是你的应用程序使用这么多内存的原因 - 商店中的每个对象都在内存中。相比之下,像NSSQLiteStoreType这样的增量存储只会将正在使用的对象保留在内存中,这样可以提高效率。