NSFileManager createDirectoryAtPath EXC_BAD_ACCESS - iphone

I have been working at this one for quite some time now but can't seem to resolve it. I have a core data application that also supports document sharing, therefore I'm trying to create a directory in the library folder for the sqlite db.
- (NSURL *)applicationPrivateDocumentsDirectory {
NSString *libraryDirectory = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
NSString *privateDocs = [libraryDirectory stringByAppendingPathComponent:#"PrivateDocuments"];
NSFileManager *fileMgr = [[NSFileManager alloc] init];
if (![fileMgr fileExistsAtPath:privateDocs]) {
NSLog(#"Does not exist");
NSError *error;
[fileMgr createDirectoryAtPath:privateDocs withIntermediateDirectories:YES attributes:nil error:&error];
NSLog(#"%#", [error description]);
}
NSURL *retURL = [NSURL fileURLWithPath:privateDocs];
return retURL;
}
The debug console outputs "Does not exist" followed by "EXC_BAD_ACCESS"
Any help is greatly appreciated.

Try to add this:
NSError *error = nil;

Related

How to copy a file from URL to document folder?

I need to copy a text file from an URL and place / overwrite it in my app's document folder and then read it back to a data variable.
I have the following code:
NSData *data;
//get docsDir
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir=[paths objectAtIndex:0];
//get path to text.txt
NSString *filePath=[docsDir stringByAppendingPathComponent:#"text.txt"];
//copy file
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
if([fileManager fileExistsAtPath:filePath]==YES){
[fileManager removeItemAtPath:filePath error:&error];
}
NSString *urlText = #"http://www.abc.com/text.txt";
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSFileManager *fileManager=[NSFileManager defaultManager];
[fileManager copyItemAtPath:urlText toPath:filePath error:NULL];
}
//Load from file
NSString *myString=[[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
//convert string to data
data=[myString dataUsingEncoding:NSUTF8StringEncoding];
It builds and complies in good way but I cannot create the text.txt file in my document folder and then pass anything to my data variable.
I'm a newbie to both IOS and Xcode, any clues will be highly appreciated. Thanks!!
NSFileManager can only handle local paths. It won't do anything useful if you give it a URL.
copyItemAtPath:toPath:error: takes an error parameter. Use it, like this:
NSError *error;
if (![fileManager copyItemAtPath:urlText toPath:filePath error:&error]) {
NSLog(#"Error %#", error);
}
You would then get this error:
Error Error Domain=NSCocoaErrorDomain Code=260 "The operation couldn’t be
completed. (Cocoa error 260.)" UserInfo=0x9a83c00 {NSFilePath=http://www.abc.com/text.txt,
NSUnderlyingError=0x9a83b80 "The operation couldn’t be completed.
No such file or directory"}
It can't read the file at http://www.abc.com/text.txt, because it is not a valid path.
as Sunny Shah stated without explanation you have to fetch the object at the URL first:
NSString *urlText = #"http://www.abc.com/text.txt";
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSURL *url = [NSURL URLWithString:urlText];
NSError *error;
NSData *data = [[NSData alloc] initWithContentsOfURL:url options:0 error:&error];
if (!data) { // check if download has failed
NSLog(#"Error fetching file %#", error);
}
else {
// successful download
if (![data writeToFile:filePath options:NSDataWritingAtomic error:&error]) { // check if writing failed
NSLog(#"Error writing file %#", error);
}
else {
NSLog(#"File saved.");
}
}
}
Always check for errors!
You should get the data from the URL and use WriteToFile
NSData *urlData = [NSData dataWithContentsOfURL: [NSURL URLWithString:urlText]];
[urlData writeToFile:filePath atomically:YES];

Warning in iCloud integration

I am trying to integrating iCloud.
Everything works fine but when I try to read a file from iCloud I get a warning Like:
Foundation called mkdir("/var/mobile/Library/Mobile Documents/.ubd/peer-E8A60A8F-FB9D-8721-F47C-hdffgdfg-v23/ftr/(A Document Being Saved By XYZ)"), it didn't return 0, and errno was set to 1.
My Code to fetch Data:
for (NSMetadataItem *item in results)
{
NSString *filename = [item valueForAttribute:NSMetadataItemDisplayNameKey];
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
MyDocument *doc = [[MyDocument alloc] initWithFileURL:url];
[doc openWithCompletionHandler:^(BOOL success) {
if (success) {
NSData *file = [NSData dataWithContentsOfURL:url];
NSString *docDir = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:#"Import/iCloud"];
if (![[NSFileManager defaultManager] fileExistsAtPath:docDir])
[[NSFileManager defaultManager] createDirectoryAtPath:docDir withIntermediateDirectories:YES attributes:nil error:nil];
NSString *pdfFile = [docDir stringByAppendingPathComponent:filename];
if(![[NSFileManager defaultManager] fileExistsAtPath:pdfFile])
[[NSFileManager defaultManager] createFileAtPath:pdfFile contents:file attributes:nil];
NSLog(#"Successfully loaded data from cloud file name %#", filename);
}
else
{
NSLog(#"Failed to load data");
}
}];
}
}
It looks like you have a partially written file in iCloud (based on the A Document Being Saved By XYZ in the error), and your meta data query has returned that to you since it also matches the filename. I ran into a similar situation a few weeks ago and solved it by using the exact path to the file, as in:
NSString *filepath = [containerURL.path stringByAppendingPathComponent:#"MyFileName"];
NSPredicate *pred = [NSPredicate predicateWithFormat: #"%K == %#", NSMetadataItemPathKey, filepath];
[query setPredicate:pred];

What's wrong with my copy here?

I'm trying to copy a file from my application bundle to my app's documents directory. I'm getting an error, "Cocoa Error 262". What am I doing wrong? Here's my code:
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"CoreData.sqlite"];
NSURL *initialURL = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:#"CoreData" ofType:#"sqlite"]];
NSError *error = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:[initialURL absoluteString]]) {
NSLog(#"Original does not exist. \nPath: %#", [initialURL absoluteString]);
}
if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURL absoluteString]]) {
NSLog(#"Destination file does not exist. \nPath: %#", [storeURL absoluteString]);
[[NSFileManager defaultManager] copyItemAtURL:initialURL toURL:storeURL error:&error];
NSLog(#"Error: %#", [error description]);
}
The problem is you're initializing a URL with a plain old file path.
NSURL *initialURL =
[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:#"CoreData"
ofType:#"sqlite"]];
Use [NSURL fileURLWithPath:] instead.
The error you are getting is
NSFileReadUnsupportedSchemeError
Read error because the specified URL scheme is unsupported
which I believe would mean one of your paths is not forming correctly. perhaps write these paths to the log and see if they are coming out as you expect them to.
I've solved the problem, although to be honest, I'm not sure what it was. I have to go over the working code again, but here it is:
NSError *error = nil;
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", #"CoreData", #"sqlite"]];
//if file does not exist in document directory, gets original from mainbundle and copies it to documents.
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSString *defaultFilePath = [[NSBundle mainBundle] pathForResource:#"CoreData" ofType:#"sqlite"];
[[NSFileManager defaultManager] copyItemAtPath:defaultFilePath toPath:filePath error:&error];
if (error != nil) {
NSLog(#"Error: %#", error);
}
}
Edit:
I suspect that the path to the application directory was incorrect, given that the body of the generated applicationDocumentsDirectory looks different than the method used for the value of the documentsDorectory variable shown above.
Error 262 is defined in FoundationErrors.h to be NSFileReadUnsupportedSchemeError.
I'd suggest that you use NSLog() to write out the literal values of the two URLs that you're using and make sure that they are file:// URLs and that they look complete.

importing sqlite to coredata

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!!
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
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
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];
}
}
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"];
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.

How to rename directories?

I have created a folder within the Documents folder in my application directory .
I wanted to rename that folder through code,but not able to understand how to do it.
Please help me out.
Have you tried?
NString *newDirectoryName = #"<new folder name>";
NSString *oldPath = #"<path to the old folder>";
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newDirectoryName];
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:oldPath toPath:newPath error:&error];
if (error) {
NSLog(#"%#",error.localizedDescription);
// handle error
}
NSString *oldDirectoryPath = #"Type your old directory Path";
NSArray *tempArrayForContentsOfDirectory =[[NSFileManager defaultManager] contentsOfDirectoryAtPath:oldDirectoryPath error:nil];
NSString *newDirectoryPath = [[oldDirectoryPath stringByDeletingLastPathComponent]stringByAppendingPathComponent:newDirectoryname];
[[NSFileManager defaultManager] createDirectoryAtPath:newDirectoryPath attributes:nil];
for (int i = 0; i < [tempArrayForContentsOfDirectory count]; i++)
{
NSString *newFilePath = [newDirectoryPath stringByAppendingPathComponent:[tempArrayForContentsOfDirectory objectAtIndex:i]];
NSString *oldFilePath = [oldDirectoryPath stringByAppendingPathComponent:[tempArrayForContentsOfDirectory objectAtIndex:i]];
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:oldFilePath toPath:newFilePath error:&error];
if (error) {
// handle error
}
}
Using moveItemAtPath should work. Sometimes the directory isn't actually "renamed" but really moved to another place. In which case the target path directory structure needs to be created as well.
Here a code snippet i'm using that works well :
-(BOOL)renameDir:(NSString *)dirPath asDir:(NSString *)newDirPath cleanExisting:(BOOL)clean
{
NSError *error = nil;
NSFileManager *fm = [NSFileManager defaultManager];
if (clean && [fm fileExistsAtPath:newDirPath])
{
[fm removeItemAtPath:newDirPath error:&error];
if (error != nil)
{
NSLog(#"Error while renameDir %# as %# :\n%#",dirPath,newDirPath,error);
return NO;
}
}
//Make sure container directories exist
NSString *newDirContainer = [newDirPath stringByDeletingLastPathComponent];
if (![fm fileExistsAtPath:newDirContainer])
{
[fm createDirectoryAtPath:newDirContainer withIntermediateDirectories:YES attributes:nil error:&error];
}
if (error==nil)
{
[fm moveItemAtPath:dirPath toPath:newDirPath error:&error];
}
if (error!=nil)
{
NSLog(#"error while moveItemAtPath : %#",error);
}
return (error==nil);
}
This always work
NSLog (#"Copying download file from %# to %#", aPath, bPath);
if ([[NSFileManager defaultManager] fileExistsAtPath: bPath]) {
[[NSFileManager defaultManager] removeItemAtPath: bPath
error: &error];
}
if (![[NSFileManager defaultManager] copyItemAtPath: aPath
toPath: bPath
error: &error]){}
if ([[NSFileManager defaultManager] removeItemAtPath: aPath
error: &error]) {}
This is good article for renaming, deleting and create files.
// For error information
NSError *error;
// Create file manager
NSFileManager *fileMgr = [NSFileManager defaultManager];
// Point to Document directory
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
// Rename the file, by moving the file
NSString *filePath2 = [documentsDirectory stringByAppendingPathComponent:#"file2.txt"];
// Attempt the move
if ([fileMgr moveItemAtPath:filePath toPath:filePath2 error:&error] != YES)
NSLog(#"Unable to move file: %#", [error localizedDescription]);
// Show contents of Documents directory
NSLog(#"Documents directory: %#",
[fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error]);
http://iosdevelopertips.com/data-file-management/iphone-file-system-creating-renaming-and-deleting-files.html