Core Data应用程序中的“另存为...”方法

时间:2011-04-18 16:08:09

标签: cocoa core-data

CD对我来说是一个巨大的学习曲线,对我来说还有一点让步,但是下面的任何帮助都可以让我把目前的重量提升到肩膀上!

我正在尝试为我的CD应用中的用户编写一个实现“另存为...”的方法。

到目前为止,我已经:

[saveAsPanel beginSheetModalForWindow:window completionHandler:^(NSInteger userResult)
{
if (userResult == NSOKButton) {
    NSPersistentStoreCoordinator *psc = [self persistentStoreCoordinator];
    NSURL *oldURL = [self URLOfInternalStore]; //returns the current store's URL
    NSURL *newURL = [saveAsPanel URL];
    NSError *error = nil;
    NSPersistentStore *oldStore = [psc persistentStoreForURL:oldURL];
    NSPersistentStore *sqLiteStore = [psc migratePersistentStore:oldStore
                                                           toURL:newURL
                                                         options:nil
                                                        withType:NSXMLStoreType
                                                           error:&error];
}
}];

不幸的是,我刚收到错误:

无法从此NSManagedObjectContext的协调器访问Object的持久存储。

我应该'删除'然后'addPersistentStore ...'将其更新为新网址吗?该文档似乎表明所有这些都将在“迁移”方法中处理。

提前致谢!

编辑:

好吧,我已经想出了自己的'脏'方法。我可以想象这不是一种经过批准的做事方式,但是没有出现任何错误,应用程序始终按预期工作(不是我经常说的那样!):

        -(IBAction)saveAsAction:(id)sender
    {
        NSSavePanel *saveAsPanel = [NSSavePanel savePanel];
        [saveAsPanel beginSheetModalForWindow:window completionHandler:^(NSInteger userResult)
        {
        if (userResult == NSOKButton) {
            [self saveAction:@"saveAsCalling"];
            NSURL *newURL = [saveAsPanel URL];
            NSError *error = nil;
            [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:internalStore] toURL:newURL error:&error];
//internalStore is a hard-wired NSString that holds the path to the bundle's database
        }
        }];
    }

    -(IBAction)loadAction:(id)sender
    {
        NSOpenPanel *loadPanel = [NSOpenPanel openPanel];
        [loadPanel beginSheetModalForWindow:window completionHandler:^(NSInteger userResult)
         {
             if (userResult == NSOKButton) {
                 [self saveAction:@"loadCalling"];
                 NSURL *newURL = [loadPanel URL];
                 NSURL *oldURL = [NSURL fileURLWithPath:internalStore];
                 NSError *error = nil;
                 NSPersistentStoreCoordinator *psc = [SELF_MOC persistentStoreCoordinator];
                 [psc removePersistentStore:[[self persistentStoreCoordinator] persistentStoreForURL:oldURL] error:&error];
                 [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:newURL options:nil error:&error];
                 [[NSFileManager defaultManager] removeItemAtURL:oldURL error:&error];
                 [[NSFileManager defaultManager] copyItemAtURL:newURL toURL:oldURL error:&error];
                 [psc removePersistentStore:[[self persistentStoreCoordinator] persistentStoreForURL:newURL] error:&error];
                 [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:oldURL options:nil error:&error];
             }
         }];
    }

基本的理由是:做一个'SaveAs ...'我只需将mainBundle中的SQLLite存储文件复制到用户选择的任何地方,并根据TechZen的建议将其重命名为他们想要的内容。

要执行'加载',然后我首先从包的文件中删除PersistentStore,添加用户刚才选择的那个。删除捆绑存储(理论上现在没有使用),然后将用户的选择复制回捆绑包中。最后,执行remove和addPersistentStore的两个操作,将应用程序指向它的bundle文件,该文件现在是用户的选择。

希望这是有道理的。如果有人对如何不专业的方法有任何想法,那么请 - 请善待,因为我很新 - 让我知道。我找不到更优雅的东西。

我知道Apple不喜欢你使用removePersistentStore和addPersistentStore但是,正如我所说的,没有报告任何错误(在我的实际代码中,我分散了整个NSLog行报告了什么错误)。

1 个答案:

答案 0 :(得分:0)

您只能在基于文档的应用中使用SaveAs...。如果您使用Core Data作为模型,则需要使用NSPersistentDocument来保存数据。它提供您所寻求的SaveAs...功能。

Straight Core Data用于更多类似数据库的应用程序,其中整个应用程序可以从一个数据集(或多或少)运行。