我正在开发一个非常糟糕的旧 Objective-C 应用程序。我正在处理的功能涉及从核心数据中获取不同的记录类型并将它们发送到服务器。并且必须先发送一种记录类型 (A),然后才能发送另一种记录类型 (B)。
编辑:A
指的是 ActivitySession
对象,B
指的是 ActivityRun
对象。
这就是问题所在:在应用程序的某处,有某种监听器在发送 A 记录后删除所有 B 记录。我花了一段时间试图找出发生这种情况的地方,但我没有运气。我的解决方案是在发送 A 记录之前将所有 B 记录加载到内存中(认为即使 B 记录从核心数据中删除,它们仍将存在于内存中)。但是我发现从核心数据中删除B记录后,我的记录数组也被清除了。
这是我正在谈论的逻辑的核心:
__block NSArray* activityRuns = [coreData fetchByEntitiyName:@"ActivityRun"];
NSLog(@"---> Sending %@ students", @([students count]));
return [self sendStudents:students withApiKey:apiKey]
.then(^{
// This must happen before sending anything with activity references
NSLog(@"---> Fetching activities");
return [self fetchActivitiesWithApiKey:apiKey];
})
.then(^{
NSArray* data = [coreData fetchByEntitiyName:@"ActivitySession"];
NSLog(@"---> Sending %@ activity sessions", @([data count]));
return [self sendActivitySessions:data withApiKey:apiKey].catch(failLogger(@"Failed to upload activity sessions", nil));
})
.then(^{
NSLog(@"---> Sending %@ activity runs", @([activityRuns count]));
return [self sendActivityRuns:activityRuns withApiKey:apiKey].catch(failLogger(@"Failed to upload activity runs", nil));
})
activityRuns
是我尝试发送的内存数据(使用 [self sendActivityRuns:activityRuns withApiKey:apiKey]
)。以下是 fetchByEntitiyName
的定义方式:
- (NSArray*) fetchByEntitiyName:(NSString*) entityName {
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] initWithEntityName:entityName];
NSError* error = nil;
NSArray* results = [_mainQueueContext executeFetchRequest:fetchRequest error:&error];
if (results == nil) {
ELog(@"--- Failed to fetch %@: %@", entityName, error);
return @[];
}
return results;
}
activityRuns
没有在除了上面的代码片段之外的任何地方使用/传递,其中每个事件运行都是使用 HTTP 请求发送的。我尝试在创建数组之后(对象有效并包含数据)和发送之前(它们都是 nil
)添加断点。
当某些内容删除记录时,如何防止核心数据在我的内存对象中乱码?
最佳答案
有几种方法可以做到这一点:
- 最明显的是调用 NSManagedObjectContext.deleteObject,只需查找
deleteObject
并在那里放置断点。 - 另一种是如果A和B有级联删除关系,你删除了parent,那么B也被删除了。例如,如果一个 Student 在如下属性中有一个 ActivityRun-s 列表:student.activityRuns(子对象数组),或反向属性 - activityRun.student(单个父对象),并且在您的 CoreData 模型中设置了此属性作为级联删除,如果你删除一个学生,所有的 activityRuns 都将消失。如果您使用“on delete set null”而不是“on delete cascade”,则子项不会被自动删除,但您必须在需要时手动删除它们。另一种方法是通过设置
activityRun.student = nil;
将子项与父项“分离”,它应该具有相同的效果(需要时再次必须手动删除)。 - 另一种选择是,如果您对该数据库执行原始 SQL DELETE 查询
有一种方法可以查看幕后发生的所有 CoreData SQL 命令 - see here .
关于ios - 防止内存中的核心数据对象被不相关的代码删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50300708/