10

I just started with iPhone development. In one of the example where I had to display some data stored in sqlite db in a table view in a tabbar controller, I had to move a sqlite file from application bundle to the documents folder.

I used the application template - iOS > Application > Window-based application for iPhone (Used core data for storage)

In the template generated by XCode (base sdk set to latest iOS = 4.2), the following code was there...

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

In trying to get a path to documents folder, I used the method given above like this...

NSString *documentDirectory = [self applicationDocumentsDirectory];

This gave a warning - warning: incompatible Objective-C types initializing 'struct NSURL *', expected 'struct NSString *'

So I changed the code to following...

// Added the message absoluteString over here
NSString *documentDirectory = [[self applicationDocumentsDirectory] absoluteString];

NSString *writableDBPath = [documentDirectory stringByAppendingPathComponent:@"mydb.sqlite"];
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"mydb.sqlite"];
BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
   NSLog(@"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}

And BOOM!!! It gave the error that - 'Failed to create writable database file with message 'The operation couldn’t be completed. No such file or directory'.'

How should I find the path to documents directory since the method applicationDocumentsDirectory generated by XCode template does not work for me.

Also, can somebody throw some light on the purpose of applicationDocumentsDirectory method given above.

Thanks

vikmalhotra
  • 9,981
  • 20
  • 97
  • 137
  • I was getting error because i was not adding the file name on the writableDBPath. This example helped me fixing it. Thanks! +1 – voghDev Nov 26 '14 at 11:52

2 Answers2

20

heres a simple way to do it:

    NSFileManager *fmngr = [[NSFileManager alloc] init];
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"mydb.sqlite" ofType:nil];
    NSError *error;
    if(![fmngr copyItemAtPath:filePath toPath:[NSString stringWithFormat:@"%@/Documents/mydb.sqlite", NSHomeDirectory()] error:&error]) {
         // handle the error
         NSLog(@"Error creating the database: %@", [error description]);

    }
    [fmngr release];
Rich
  • 1,082
  • 7
  • 11
  • 2
    Rich you're right but a little out of date. From the current docs: "This will always return the same instance of the file manager. The returned object is not thread safe. In Mac OS X v 10.5 and later you should consider using [[NSFileManager alloc] init] rather than the singleton method defaultManager. Using [[NSFileManager alloc] init] instead, the resulting NSFileManager instance is thread safe." – Hack Saw Jan 22 '11 at 22:18
  • So, I'd make a couple of small changes to the above: I'd change the first line's RHS to [[NSFileManager alloc] init], and I'd add [fmngr release]; after the if block. – Hack Saw Jan 22 '11 at 22:20
  • Thanks for pointing that out. I now remember reading that when 4.0 came out, but I guess I just crammed it to the back of my head learning about all the other updates. – Rich Jan 23 '11 at 17:57
5

I just ran into this myself a few days ago. Don't force things down the Path path, embrace the NSURL path. It won't take but a short time to get how to use them.

As to the method, it's simply asking the system to hand you a URL to the standardized documents directory for the application. Use this and most everything regarding where you put new files will be correct.

Hack Saw
  • 2,741
  • 1
  • 18
  • 33