无法将sqlite文件从app bundle复制到文档目录:getting(Cocoa error 260)

时间:2013-07-24 20:36:12

标签: ios sqlite core-data bundle

我正在尝试使用下面的代码将我的sqlite文件从app bundle复制到文档目录中

-(id)init {

    self = [super init];
    if (self) {

// 1.为UIManagedDocument

创建数据库文件的句柄
        NSURL *docURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        docURL = [docURL URLByAppendingPathComponent:@"DefaultDatabase"];
        self.document =  [[UIManagedDocument alloc] initWithFileURL:docURL]; // URL of the location of document i.e. /documents directory
    NSLog(@" URL document");

        //set our document up for automatic migrations

        if (self.document) {
            NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES],
            NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES],
            NSInferMappingModelAutomaticallyOption, nil];

            self.document.persistentStoreOptions = options;

            // Register for Notifications

            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(objectsDidChange:) name:NSManagedObjectContextObjectsDidChangeNotification object:self.document.managedObjectContext];

            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:self.document.managedObjectContext];
        } else {         
            NSLog(@"The UIManaged Document could not be initialized");

        }

// 2.检查首次运行时是否存在持久性存储文件

    if (!([[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]])) {
        NSLog(@" persistent file not found trying to copy from app bbundle");
        NSString *docFileName = [UIManagedDocument persistentStoreName];
        NSString *docFilePath = [[NSBundle mainBundle] pathForResource:docFileName ofType:@"sqlite"];
        **NSLog(@" doc file path = %@", docFilePath);**
        if (docFilePath) { // found the database file in app bundle
            NSLog(@" found file in bundle");
            //Production: Copy from app bundle.
            NSError *error = nil;
            NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *copyToPath  = [searchPaths lastObject];
            if([[NSFileManager defaultManager] copyItemAtPath:docFilePath toPath:copyToPath error:&error]){
                NSLog(@"File successfully copied");
            } else { // if could not locate the file
                [[[UIAlertView alloc]initWithTitle:NSLocalizedString(@"error", nil) message: NSLocalizedString(@"failedcopydb", nil)  delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", nil)  otherButtonTitles:nil] show];
                NSLog(@"Error description-%@ \n", [error localizedDescription]);
                NSLog(@"Error reason-%@", [error localizedFailureReason]);
            }
        }
    }
}
return self;

}

a)我使用数据加载器应用程序创建了.sqlite文件,该应用程序使用UIManagedDcoument将数据添加到Core Data。 .sqlite文件在文档目录中生成。

b)我将* .sqlite文件添加到资源文件夹并将其添加到bundle。如果我使用Terminal检查应用程序包..我在bundle目录下看到'persistent store'和<app name.momd>文件。没有扩展名为.sqlite的文件

c)但是在上面的代码中,当我使用代码行检查应用程序包中是否存在文件时,它是成功的。所以文件存在于bundle

   NSString *file = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];

d)但是当尝试复制时,它会失败并给我(Cocca Error 206)意味着它无法在应用程序包中找到.sqlite文件。

  if([[NSFileManager defaultManager] copyItemAtPath:file toPath:copyToPath error:&error])

这符合我在应用程序包目录下看不到.sqlite文件的事实,而是看到持久存储和.momd文件。

所以我哪里出错了?

修改

这是我如何生成mydata.sqlite文件的解释。

我正在使用Core Data,并且希望在首次向用户启动应用程序时提供预先打包的数据库。所以我使用数据加载器应用程序为我创建.sqlite文件。我正在使用UIManagedDocument来获取核心数据。运行应用程序后,我看到在文档目录下创建了一个mydata.sqlite目录。目录结构如下

/用户//.../文件/ mydata.sqlite / storeContent / persistenStore。

所以基本上不是创建文件,而是创建一个扩展名为.sqlite的目录,我看到persistentStore文件。因此,当我尝试在构建阶段下在目标应用程序包下复制资源时..添加了persistentStore而不是.sqlite文件。

我的问题描述的是正确的,我应该在我的代码中以不同的方式处理它。如果是的话,我应该做些什么来处理数据存储。

我认为.sqlite是一个文件而不是目录。请指导

由于

2 个答案:

答案 0 :(得分:0)

此行实际上不会检查文件是否存在:

NSString *file = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];

所有这一切都是在file中构建路径。如果要检查它是否存在,则需要使用[NSFileManager fileExistsAtPath:]。或者您可以返回使用pathForResource:ofType:,这在返回nil时显然是正确的。

您似乎根本没有将文件复制到捆绑包中。这是您的Xcode项目配置的问题。

答案 1 :(得分:0)

我在UIManagedDocument上阅读了apple documentation,以下是我出错的关键点

  1. 错误地处理UIManagedDocument。初始化托管文档时,请指定文档位置的URL。,而不是文档本身。如果需要添加

  2. 您可以通过创建UIManagedDocument的子类来执行其他自定义,即 覆盖persistentStoreName以自定义文档文件包中持久性存储文件的名称。

  3. 剪切并粘贴示例代码,以正确的方式处理数据文件

  4. 使用initWithFileURL创建托管文档对象:如果需要,可以在使用其托管对象上下文之前配置文档。通常,您可以设置持久性存储选项,如以下示例所示:

    NSURL *docURL = [[self applicationDocumentsDirectory]        URLByAppendingPathComponent:@"FirstDocument"];
     doc = [[UIManagedDocument alloc] initWithFileURL:docURL];
    
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
     [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
     [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
    doc.persistentStoreOptions = options;
    
    
    **if ([[NSFileManager defaultManager] fileExistsAtPath:[docURL path]]**) {
       [doc openWithCompletionHandler:^(BOOL success){
        if (!success) {
            // Handle the error.
        }
        }];
     }
      else {
       [self addInitialData];
       [doc saveToURL:docURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){
          if (!success) {
            // Handle the error.
         }
         }];
        }