【问题标题】:How to share an NSManagedObjectContext between a NSPersistentDocument and view controller?如何在 NSPersistentDocument 和视图控制器之间共享 NSManagedObjectContext?
【发布时间】:2014-04-25 03:16:07
【问题描述】:

OS X 编程新手。从 Xcode 模板开始,该模板用于使用 Core Data 的基于文档的应用程序。

在我的默认 Document.xib 中,我创建了一个 View,我使用自定义 ViewController 对其进行控制。然后我在 Document.xib 中创建了一个Managed Object Context 并创建了两个出口,一个到Document.h

@property (strong) IBOutlet NSManagedObjectContext *myManagedObjectContext;

一到ViewController.h:

@property (weak) IBOutlet NSManagedObjectContext *myManagedObjectContext;

windowControllerDidLoadDocument.m 中,然后我添加了self.myManagedObjectContext = [self managedObjectContext]

按照 ghostfly 的建议 (could not locate an NSManagedObjectModel for entity name) 我补充说:

NSLog(@"Context: %@",self.myManagedObjectContext);
NSLog(@"PS Coord : %@",self.myManagedObjectContext.persistentStoreCoordinator);
NSLog(@"MOM : %@", self.myManagedObjectContext.persistentStoreCoordinator.managedObjectModel);
NSLog(@"Entities : %@",[[self.myManagedObjectContext.persistentStoreCoordinator.managedObjectModel entities] valueForKey:@"name"]);

windowControllerDidLoad 中的 Document.m 以及我的 ViewController 的 awakeFromNib 中。在 Document.m 中似乎一切正常:所有 NSLog 语句看起来都正确,我也可以将 Entities 添加到我的 NSManagedObjectContext 但在 ViewController 中,只有第一个 NSLog 语句有效,其余的返回(null)。

我的问题:这里出了什么问题,我是否以正确的方式解决这个问题?

其他各种问题似乎建议将 AppDelegate 添加到 MainMenu.xib,但我不确定这在基于文档的应用程序中如何工作(例如,我希望每个文档都有一个单独的NSManagedObjectContext,但是如果我使用 AppDelegate,那么它们肯定都是一样的吗?),或者即使是推荐的,因为一些教程表明这是明确的不是如何做到这一点(例如这里@ 987654322@)。非常感谢您的帮助!谢谢。

【问题讨论】:

  • 为什么要在XIB中创建托管对象上下文? NSPersistentDocument已经设置了一个供你使用!
  • Volker:可能是因为我不明白我在做什么!我可以看到 NSPersistentDocument 为我设置了一个,但我不知道如何从我在 Document.xib 中使用的 ViewController 访问它...

标签: objective-c xcode macos cocoa core-data


【解决方案1】:

当您开始使用多个文档时,上述答案会产生问题 - 它不起作用,因为您只保存到最后打开的文档。你不应该尝试创建你自己的托管对象上下文,因为你必须设置所有的东西来存储数据等(这已经完成了)。这要简单得多:

您的主文档类应该是 NSPersistentDocument 的子类。如果没有,那么您可以直接替换它而不是 NSDocument。 NSPersistentDocument 有它自己的 managedObjectContext 和 persistentStoreCoordinator,您可以在文档中使用它们(存储文档相关数据)。

因此,这意味着每个文档都有自己的 managedObjectContext 和 persistentStoreCoordinator。要在其他类中访问这些,您应该将引用传递给文档。例如。在您的视图控制器子类上,为文档创建一个@IBOutlet,在接口生成器中附加文档,然后在构造函数中,将文档的 managedobjectcontext 复制到视图控制器中它自己的指针以供使用。

【讨论】:

    【解决方案2】:

    编辑:正确答案是使用 MagicalRecord (https://github.com/magicalpanda/magicalrecord) 并为自己节省大量时间!

    我之前的回答如下:

    好的,我想我已经完成了这项工作,但我不确定这是“最好的”还是“最惯用的”方式。我将非常详细地说明它,以防其他人偶然发现这个问题并且同样被所有这些如何组合在一起而感到困惑......

    首先,忘记 .xib 中的 ManagedObjectContext;我不确定什么时候适合使用它。

    我创建了一个名为 AppDelegate 的应用程序委托。在AppDelegate.h:

    #import <Cocoa/Cocoa.h>
    
    @interface AppDelegate : NSObject <NSApplicationDelegate>
    
    @property (retain) NSManagedObjectContext *managedObjectContext;
    @property (retain) NSPersistentStoreCoordinator *persistentStoreCoordinator;
    
    @end
    

    然后,在MainMenu.xib 中,我拖入一个NSObject 并将其类设置为AppDelegate 并将文件所有者的委托连接到此对象。

    Document.m,在init方法中,我添加:

    AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
    appDelegate.managedObjectContext = [self managedObjectContext];
    appDelegate.persistentStoreCoordinator = [self managedObjectContext].persistentStoreCoordinator;
    

    请注意,我最初尝试将它放在 windowControllerDidLoadNib 方法中,但这不起作用,因为它似乎是在我的 ViewControllerawakeFromNib 方法之后调用的

    然后,在 awakeFromNib 中的 ViewController.m 中,我可以通过以下方式访问上下文:

    AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
    MyEntity *test = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:[appDelegate managedObjectContext]];
    

    如果我在接下来的几天里没有发现任何问题,我会接受这个答案。

    一个悬而未决的问题是当我打开多个文档时会发生什么。他们会共享相同的上下文吗?

    【讨论】:

    • 只是为了回答您最后一个未解决的问题。每个 NSPersistentDocument 都有自己的上下文,因为每个都有自己的持久存储。
    猜你喜欢
    • 1970-01-01
    • 2017-06-06
    • 2018-01-23
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    相关资源
    最近更新 更多