我正在将一些代码从我的 Controller 移动到核心数据应用程序中的模型。
我编写了一个方法,该方法为我定期发出的特定获取请求返回 NSManagedObjectID。
+ (NSManagedObjectID*)teamProjectWithProjectId:(NSNumber *)projectId inContext:(NSManagedObjectContext*)context
{
NSFetchRequest *teamRequest = [[NSFetchRequest alloc] initWithEntityName:@"TeamProject"];
NSPredicate *teamPredicate = [NSPredicate predicateWithFormat:@"teamProjectId == %@",projectId];
teamRequest.predicate = teamPredicate;
TeamProject *teamProject = [[context executeFetchRequest:teamRequest error:nil] lastObject];
if (teamProject)
{
return [teamProject objectID];
}
else
{
return nil;
}
return nil;
}
现在我需要在任何地方使用我这样做的方法:
NSManagedObjectID *teamProjectMoId = [TeamProject teamProjectWithProjectId:projectID];
TeamProject *currentProject = nil;
if (teamProjectMoId)
{
currentProject = (TeamProject*)[self.managedObjectContext objectWithID:teamProjectMoId];
}
现在这还不算太糟糕,它可以工作,并且它尊重 NSManagedObject 不是线程安全的,而 NSManagedObjectID 是线程安全的。我很高兴能够将相当多的代码从我的 Controller 类移到我的模型类别中。
但是,这还不够好。我真的想以一种尊重线程安全的方式仅用一行代码来访问 NSManagedObject。我的理想是能够写出这样的东西:
TeamProject *currentProject = [TeamProject magicalMethodThatHandlesThreadSafety];
这可能吗?或者是否有人有任何策略为 NSManagedObject 编写干净的访问器方法?
最佳答案
您可以在需要在后台进行查找的任何地方创建一个临时 MOC。这当然是线程安全的,并且比使用 ID 更快(实际上,它很快,因为创建 MOC 本身很快)。
一种方法是通过子上下文指定 NSPrivateQueueConcurrencyType
并发类型:
+ (TeamProject*)teamProjectWithProjectId:(NSNumber *)projectId inContext:(NSManagedObjectContext*)context
{
NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
temporaryContext.parentContext = context;
NSFetchRequest *teamRequest = [[NSFetchRequest alloc] initWithEntityName:@"TeamProject"];
NSPredicate *teamPredicate = [NSPredicate predicateWithFormat:@"teamProjectId == %@",projectId];
teamRequest.predicate = teamPredicate;
TeamProject *teamProject = [[temporaryContext executeFetchRequest:teamRequest error:nil] lastObject];
return teamProject;
}
另请参阅 this post了解更多场景和解决方案。
编辑:
为了让事情更清楚,上面的方法应该从使用返回的 MO 的同一线程中调用。它只是上述方法的“扩展”,因为它使用本地创建的 MOC 包装了获取操作,该 MOC 对于该线程是私有(private)的,因此您可以安全地使用它。
换句话说,您可以从任何线程调用上述方法,并在同一线程中安全地使用返回的 MO。使用子 MOC 的技巧允许您通过创建临时私有(private) MOC 在任何线程中进行获取。
引用在另一个线程中创建的 MOC 来在当前线程中创建子 MOC 是安全的。
仍然不允许将托管对象从一个线程传递到另一个线程。
关于ios - 传递 NSManagedObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19187584/