我为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];
}
使用乐器增加内存的两个屏幕截图。
答案 0 :(得分:1)
您正在使用NSXMLStoreType persistent store,这是一种原子商店。这意味着当实例化存储并将其添加到持久性存储协调器时,整个对象图将加载到内存中。这就是你的应用程序使用这么多内存的原因 - 商店中的每个对象都在内存中。相比之下,像NSSQLiteStoreType
这样的增量存储只会将正在使用的对象保留在内存中,这样可以提高效率。