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

时间:2011-09-13 23:04:12

标签: xcode macos cocoa core-data

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

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

问题:

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

  2. 如果writeToURL:ofType:error:不同,我(表面上)在url进行商店迁移。但是如果我在writeToURL:ofType:error:中设置断点,然后点击保存,我的断点就不会被击中。为什么不呢?

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

  4. (非常)旧的视频教程提出了一种方法,可以轻松地将数据绑定到UIView,就像表格一样。跟随Xcode是不可能的,因为这么多已经改变了。有没有更新的参考资料?

  5. 代码:

    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 个答案:

答案 0 :(得分:2)

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

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

即可
-configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:

然后,您可以在需要时向文档询问managedObjectContext并编写代码。

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