ios - 传递 NSManagedObject

标签 ios objective-c model-view-controller nsmanagedobject nsmanagedobjectid

我正在将一些代码从我的 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/

相关文章:

ios - 增加 Collection View 中单元格之间的间距大小

iphone - CGRect 在动画期间不改变

php - 根据行动改变观点是不好的做法吗?

WPF - 让 ViewModel 与 WPF 无关是一个好主意吗?

javascript - 如何将 AJAX 数据从 VIEW 发送到 CONTROLLER? (PHP(MVC)+AJAX)

ios - iOS 设备中的 3D 广告

ios - Realm :获取-[__NSArrayM UTF8String]:发送到实例的无法识别的选择器

ios - UIAnimation后UI屏幕变黑

ios - 设备方向在标签栏应用程序中启动所有 View Controller

ios - 核心数据 - 按关系选择