创建新的基于文档的核心数据项目时出现问题

Posted

技术标签:

【中文标题】创建新的基于文档的核心数据项目时出现问题【英文标题】:Problems creating a new Document-based Core Data project 【发布时间】:2011-09-13 23:04:12 【问题描述】:

我正在尝试创建一个基于 Core Data 的 Mac OS X 应用程序。我在 ios 上使用过 Core Data,但使用 AppKit 时有些不同。我也在 10.7 上使用 Xcode 4.1,而且我知道 Lion 上的一些核心数据发生了变化。 Apple 提供的唯一最新参考资料是最近的 WWDC 会议,该会议承诺/建议更新 Apple.com 上的参考资料,但大多数核心数据资料都非常过时。

首先,我使用 Xcode 使用 Core Data 生成基于文档的项目。我挖空了一些主菜单位(删除了一些菜单项)并摆脱了Main Menu.xib 中的NSWindow 对象,而是用NSWindow(和子视图)创建了我自己的MyDocument.xib

问题:

    我假设持久存储控制器总是需要一个持久存储,所以如果创建了一个新文档,我只是添加一个内存存储。从磁盘打开时,我使用 SQLite 存储创建它。对吗?

    如果url 不同,我(表面上)在writeToURL:ofType:error: 中进行存储迁移。但是如果我在writeToURL:ofType:error: 中设置了一个断点,然后点击保存,我的断点就没有命中。为什么不呢?

    如果我选择“恢复为已保存”,应用程序会崩溃——很难。我必须强制退出它(并退出 Xcode)。为什么?

    (非常)旧视频教程建议了一种将数据轻松绑定到UIView 的方法,例如表格。跟随 Xcode 是不可能的,因为发生了很多变化。有没有更新的参考资料?

代码:

MyDocument.h:

#import <Cocoa/Cocoa.h>

@interface MyDocument : NSPersistentDocument

@private
    NSManagedObjectModel* mom;
    NSPersistentStoreCoordinator* psc;
    NSManagedObjectContext* moc;


@end

MyDocument.m:

#import "MyDocument.h"

@interface MyDocument ()
- (void)setUpManagedObjectModel;
- (void)setUpPersistentStoreCoordinator;
- (void)setUpManagedObjectContext;
- (BOOL)addPersistentStore:(NSString*)type url:(NSURL*)url error:(NSError**)outError;
@end

@implementation MyDocument

- (void)dealloc

    [moc release];
    [psc release];
    [mom release];
    [super dealloc];


- (id)init

    self = [super init];
    if (self)
    
        [self setUpManagedObjectModel];
        [self setUpPersistentStoreCoordinator];
        [self setUpManagedObjectContext];
    
    return self;


- (id)initWithType:(NSString *)typeName error:(NSError **)outError

    self = [super initWithType:typeName error:outError];
    if (self)
    
        [self addPersistentStore:NSInMemoryStoreType url:nil error:outError];
    
    return self;


- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError

    return [self addPersistentStore:NSSQLiteStoreType url:url error:outError];


- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError

    NSPersistentStore* currentStore = [[psc persistentStores] lastObject];
    if (![[currentStore URL] isEqual:url])
    
        NSPersistentStore* newStore = [psc migratePersistentStore:currentStore
                                                            toURL:url
                                                          options:nil
                                                         withType:typeName
                                                            error:outError];
        if (!newStore)
        
            return NO;
        
    
    return [moc save:outError];


- (NSString *)windowNibName

    // Override returning the nib file name of the document
    // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
    return @"MyDocument";


- (void)windowControllerDidLoadNib:(NSWindowController *)aController

    [super windowControllerDidLoadNib:aController];
    // Add any code here that needs to be executed once the windowController has loaded the document's window.


+ (BOOL)autosavesInPlace

    return YES;


- (BOOL)validateMenuItem:(NSMenuItem *)item

    NSLog(@"menu item: %@", [item title]);
    return YES;


#pragma mark Private Methods


- (void)setUpManagedObjectModel

    NSURL* modelUrl = [[NSBundle mainBundle] URLForResource:@"MyDatabase" withExtension:@"momd"];
    mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelUrl];


- (void)setUpPersistentStoreCoordinator

    psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];


- (void)setUpManagedObjectContext

    moc = [[NSManagedObjectContext alloc] init];
    [moc setPersistentStoreCoordinator:psc];


- (BOOL)addPersistentStore:(NSString*)type url:(NSURL*)url error:(NSError**)outError

    NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
    NSPersistentStore* ps = [psc addPersistentStoreWithType:type
                                              configuration:nil
                                                        URL:url
                                                    options:options
                                                      error:outError];
    return (ps != nil);


@end

【问题讨论】:

【参考方案1】:

如果您使用NSPersistentDocument,默认情况下所有这些都是为您处理的,您无需进行任何核心数据设置。 NSPersistentDocument 将自动处理持久存储的创建、保存和迁移。

如果要控制持久存储的配置方式,只需覆盖

-configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:

然后,您可以在需要时向文档索要其managedObjectContext 并编码。

我强烈建议您阅读 Apple 的 NSPersistentDocument tutorial 以了解更多详细信息。

【讨论】:

您链接到的教程已过期。尤其是“创建用户界面”部分,它描述了 Xcode (4) 中不再存在的步骤/功能。 另外,我不确定底层的 NSPersistentDocument 类是如何获得它的 MOM 的。这绝对不是来自我的数据模型,至少,我不能说。 您的数据模型必须与NSPersistentDocument 类命名相同,才能自动运行。即如果你的文档类是SFDocument,那么你的数据模型应该命名为SFDocument.xcdatamodel。如果您在 Xcode 中使用 Core Data Document Application 模板,这将自动完成。 原来数据模型不需要特别命名。来自NSPeristentDocumentmanagedObjectModel 方法的文档:“默认情况下,框架将创建应用程序及其框架中找到的所有模型的合并模型。子类可以返回特定模型以用于创建持久存储。”

以上是关于创建新的基于文档的核心数据项目时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

尝试创建新的 Google API 项目时出现 FAILED_PRECONDITION

在核心数据项目中加载视图控制器时出现问题

核心数据:重新打开文档时出现奇怪的绑定错误。帮助?

创建新项目时出现 Grails 2.3.7 错误

尝试为对象设置值时出现 NullReferenceException

设置 Neo4J J2EE 项目时出现问题