我有一个存储测量数据的 CoreData 配置。数据按 Session
分组,因此每个 Session
实体与 SensorData
具有一对多关系。删除规则设置为 Cascade
。我还有一个“全部删除”按钮。当它被按下时,我运行以下代码。
// All sessions (cascading)
[self.context performBlockAndWait:^{
// Fetch only managedObjectID to reduce memory impact
NSFetchRequest *sessionsRequest = [NSFetchRequest fetchRequestWithEntityName:@"Session"];
[sessionsRequest setIncludesPropertyValues:NO];
NSError *sessionsError;
NSArray *allSessions = [self.context executeFetchRequest:sessionsRequest error:&sessionsError];
if (sessionsError) {
NSLog(@"Failed to fetch all sessions. %@", sessionsError);
}
// Release fetch request
sessionsRequest = nil;
// Loop and delete
int i = 0;
for (NSManagedObject *session in allSessions) {
NSLog(@"Deleting session (%d / %d)", ++i, allSessions.count);
if (i != allSessions.count) {
[self.context deleteObject:session];
}
}
NSLog(@"All session deleted.");
}];
NSLog(@"Saving.");
[self.context performBlock:^{
[self.document saveToURL:self.documentPath
forSaveOperation:UIDocumentSaveForOverwriting
completionHandler:^(BOOL success){
NSLog(@"Document saved %@.", success ? @"successfully" : @"unsuccessfully");
}];
}];
NSLog(@"Done saving.");
发生的事情是我得到如下日志输出,因此执行速度相当快。但是 UI 然后卡住并且 RAM 使用火箭。 有大约 60 个 session 和大约 100 万个测量值(每个测量值 3 个浮点值),最终 RAM 使用量太大,应用程序在 20 分钟左右后崩溃,但所有条目仍然存在。
显然节省在这里发挥作用,但我做错了什么?感谢任何指点。
日志输出:
2015-08-13 15:16:56.825 MyApp[4201:1660697] Deleting session (1 / 61)
2015-08-13 15:16:56.826 MyApp[4201:1660697] Deleting session (2 / 61)
.
.
.
2015-08-13 15:16:56.862 MyApp[4201:1660697] Deleting session (60 / 61)
2015-08-13 15:16:56.863 MyApp[4201:1660697] Deleting session (61 / 61)
2015-08-13 15:16:56.863 MyApp[4201:1660697] All session deleted.
2015-08-13 15:16:56.864 MyApp[4201:1660697] Saving.
2015-08-13 15:16:56.864 MyApp[4201:1660697] Done saving.
更新
我编辑了程序,首先删除了测量数据,并通过设置获取限制来降低 RAM(如建议的那样)。但是,如果我删除 200 个 SensorData
,保存大约需要 3 秒,除了前 ~1000 个条目。不过删除速度很快。请参阅下面的跟踪。
我想在不删除文档的情况下解决这个问题。感觉像是一个 hack(虽然可能是一个很好的 hack)。
最佳答案
占用大量内存的是您正在加载所有 session :
NSArray *allSessions = [self.context executeFetchRequest:sessionsRequest error:&sessionsError];
尝试像这样加载 100 x 100:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[self.context setUndoManager:nil];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Session" inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
[fetchRequest setIncludesPropertyValues:NO];
[fetchRequest setFetchLimit:100];
NSError *error;
NSArray *items = [self.context executeFetchRequest:fetchRequest error:&error];
while ([items count] > 0) {
@autoreleasepool {
for (NSManagedObject *item in items) {
[self.context deleteObject:item];
}
if (![self.context save:&error]) {
NSLog(@"Error deleting %@ - error:%@",self.entityName, error);
}
}
items = [self.context executeFetchRequest:fetchRequest error:&error];
}
关于ios - CoreData - 删除所有实体消耗 RAM 并需要很长时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31989634/