importing sqlite to coredata

2020-06-07 05:26发布

问题:

I have imported sqlite prepopulated dbs to my coredata projects before, but now I have created a project in the 3.2.5. xcode, wich changes nsurl for nstring in the AppDelegate, so I went with that, But now my sqlite doesnt import to the project,

if I leave my PersistentStoreCoordinator to create the new db blank it works fine,

 NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"ChildCare_v02.sqlite"];

but when I change the code to import the prepopulated db (called the same just to clarify), it gives me a warning and crashes,

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator_ != nil) {
return persistentStoreCoordinator_;
}
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"ChildCare_v02.sqlite"]; //WARNING !! here
NSURL *storeUrl = [NSURL fileURLWithPath:storePath]; 
//NSURL *storeURL = [[self applicationDocumentsDirectory]    URLByAppendingPathComponent:@"ChildCare_v02.sqlite"]; //actual SDK style for blank db

// Put down default db if it doesn't already exist
    NSFileManager *fileManager = [NSFileManager defaultManager];
   if (![fileManager fileExistsAtPath:storePath]) {
    NSString *defaultStorePath = [[NSBundle mainBundle]  pathForResource:@"ChildCare_v02" ofType:@"sqlite"];
    if (defaultStorePath) {
        [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
    }
    }
NSError *error = nil;
persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc]  initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {


NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
    }    
    return persistentStoreCoordinator_;
    }

THIS is the crash log in console

-[NSURL stringByAppendingPathComponent:]: unrecognized selector sent to instance  0x5b40e50
 2011-02-15 21:06:59.245 Staff_02c[469:207] *** Terminating app due to uncaught  exception 'NSInvalidArgumentException', reason: '-[NSURL stringByAppendingPathComponent:]:     unrecognized selector sent to instance 0x5b40e50'

How to fix this please?? Just when I tough I was getting Core data !! dough!!

回答1:

apple changed the helper method that returns the application dictionary in the core data templates.

You are relying on this version:

- (NSString *)applicationDocumentsDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

but apple changed it to this version

- (NSURL *)applicationDocumentsDirectory {
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

to fix it, just change this.

NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"ChildCare_v02.sqlite"]; //WARNING !! here
NSURL *storeUrl = [NSURL fileURLWithPath:storePath]; 
//NSURL *storeURL = [[self applicationDocumentsDirectory]    URLByAppendingPathComponent:@"ChildCare_v02.sqlite"]; //actual SDK style for blank db

to this

//NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"ChildCare_v02.sqlite"]; //WARNING !! here
//NSURL *storeUrl = [NSURL fileURLWithPath:storePath]; 
NSURL *storeUrl = [[self applicationDocumentsDirectory]    URLByAppendingPathComponent:@"ChildCare_v02.sqlite"]; //actual SDK style for blank db

sorry, but omfg



回答2:

thanks Ishu, you helped me a lot by pointing the NSArray way!!!

this was the solution I ended up by enlightenment !

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

if (persistentStoreCoordinator_ != nil) {
    return persistentStoreCoordinator_;
}



NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"ChildCare_v02.sqlite"];

NSString *storePath = [[NSBundle mainBundle] pathForResource:@"ChildCare_v02" ofType:@"sqlite"];


NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"ChildCare_v02.sqlite"]; //este es el que sirve!!! CREE ESTE

NSLog(@"store URL %@", storeURL);

    // Put down default db if it doesn't already exist
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:writableDBPath]) {
    NSLog(@"proceda aqui");
    NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"ChildCare_v02" ofType:@"sqlite"];
    NSLog(@"no existe todavia");
    NSLog(@"defalultStorePath %@", defaultStorePath);


    if (defaultStorePath) {
      [fileManager copyItemAtPath:defaultStorePath toPath:writableDBPath error:NULL];
        NSLog(@"storePath= %@", storePath);
    }
}    

NSError *error = nil;
persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {

NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
    }    

   return persistentStoreCoordinator_;
    }

hope it helps some noob like me wanting to import prepopulated sqlite to a coredata db, note that first need to create blank db, to keep the structure and then populated (I used SQLite database browser to import CSV columns to my sqlite)

ss9



回答3:

You don't need to use NSString paths at all, it can all be done with NSURL methods.

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Database.sqlite"];

// If the database doesn't exist copy in the default one
if (![storeURL checkResourceIsReachableAndReturnError:NULL])
{
    NSURL *defaultStoreURL = [[NSBundle mainBundle] URLForResource:@"Database" withExtension:@"sqlite"];

    if ([defaultStoreURL checkResourceIsReachableAndReturnError:NULL])
    {
        NSFileManager *fileManager = [NSFileManager defaultManager];
        [fileManager copyItemAtURL:defaultStoreURL toURL:storeURL error:NULL];
    }
}


回答4:

stringByAppendingPathComponent this method is instance method of NSString class.so you cant access this method on NSURL.

so for correction change this line

NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"ChildCare_v02.sqlite"];

by this code

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"ChildCare_v02.sqlite"];


回答5:

The crash isn't related specifically to Core Data.

Looks like you're calling a method that doesn't exist.

In NSURL the method is "URLByAppendingPathComponent".

If you want stringByAppendingPathComponent, that's in NSString.

You most likely had a warning for this during build.