我正在将一些代码从我的控制器移到核心数据应用程序中的模型中。

我编写了一种方法,该方法针对我定期发出的特定提取请求返回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是线程安全的。我很高兴能够将很多代码从控制器类中移出到模型类别中。

但是,这还不够好。我真的想以尊重线程安全的方式仅用一行代码访问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(该线程专用)包装了提取操作,因此您可以安全地使用它。

换句话说,您可以从任何线程调用上述方法,并在同一线程中安全地使用返回的MO。使用子MOC的技巧使您可以通过创建临时私有MOC在任何线程中进行访存。

可以安全地引用在另一个线程中创建的MOC,以在当前线程中创建子MOC。

仍然确实不允许将托管对象从一个线程传递到另一个线程。

关于ios - 传递NSManagedObject,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19187584/

10-12 16:23