How to move a directory to a new location on iPhone - iphone

Here's my method which should simply move the contents of a directory from /someDirectory to /addons/id/UUID:
CFUUIDRef uuidObj = CFUUIDCreate(nil); //create a new UUID
//get the string representation of the UUID
NSString *uuidString = (NSString*)CFUUIDCreateString(nil, uuidObj);
//MOVE the addon to the addons directory addons/shortname/UUID
NSString *pathToAddon = [LWEFile createDocumentPathWithFilename:[NSString stringWithFormat:#"%#", relPath]];
NSString *pathToAddonDest = [LWEFile createDocumentPathWithFilename:[NSString stringWithFormat:#"addons/%#/%#", [character objectForKey:#"shortName"], uuidString]];
// move the files
NSError* error;
if([[NSFileManager defaultManager] moveItemAtPath:pathToAddon toPath:pathToAddonDest error:&error] != YES)
{
NSLog(#"Unable to move file: %#", [error localizedDescription]);
}
//release the uuid stuff
[uuidString release];
CFRelease(uuidObj);
The move fails with The operation couldn’t be completed. (Cocoa error 4.). However the same code works if I change pathToAddonDest to:
NSString *pathToAddonDest = [LWEFile createDocumentPathWithFilename:[NSString stringWithFormat:#"addons/%#", [character objectForKey:#"shortName"], uuidString]];
So I can write from /someDirectory to /addons/someDirectory but not from /someDirectory to /addons/someDirectory/UUID.
Any ideas why a seemingly simple rename wouldn't work in this way?

You should create directory before before you could move it there.
/addons/someDirectory/UUID --- create this path before you try moving the content.

Related

"The operation couldn’t be completed. (Cocoa error 512.)"

I have this code, which should be working perfectly, but I can't udnerstand why it isn't:
+(NSString *)writeImageToFile:(UIImage *)image {
NSData *fullImageData = UIImageJPEGRepresentation(image, 1.0f);
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Images/"];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = NO;
BOOL directoryExists = [fileManager fileExistsAtPath:path isDirectory:&isDirectory];
if (directoryExists) {
NSLog(#"isDirectory: %d", isDirectory);
} else {
NSError *error = nil;
BOOL success = [fileManager createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error];
if (!success) {
NSLog(#"Failed to create directory with error: %#", [error description]);
}
}
NSString *name = [NSString stringWithFormat:#"%#.jpg", [JEntry generateUuidString]];
NSString *filePath = [path stringByAppendingPathComponent:name];
NSError *error = nil;
BOOL success = [fullImageData writeToFile:filePath options:NSDataWritingAtomic error:&error];
if (!success) {
NSLog(#"Failed to write to file with error: %#", [error description]);
}
return filePath;
}
It passed the directoryExists without an error, but when it gets to writeToFile, it gives me this error:
Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" UserInfo=0x5634ee0 {NSFilePath=/var/mobile/Applications/5E25F369-9E05-4345-A0A2-381EDB3321B8/Documents/Images/18DAE0BD-6CB4-4244-8ED1-9031393F6DAC.jpg, NSUnderlyingError=0x5625010 "The operation couldn’t be completed. Not a directory"}
Any ideas why this might be?
I was able to reproduce your error when writing a file first in the path #"Documents/Images/", then trying to write the image using your code.
I think there are two possible scenarios for this:
1) You created that file by mistake at a previous execution of your app. This will be solved if you reset the simulator using the menu: iOS Simulator > Reset Contents and Settings, and uninstalling the app from your device: Long press > click on the x symbol.
2) There is some code somewhere else in your app that creates this file. If this is the case, you should find this code and remove it.
From FoundationErrors.h:
NSFileWriteUnknownError = 512
Try using withIntermediateDirectories:YES.
In my case a period '.' in the directory name (e.g. ~/Documents/someDir.dir/somefile) was the cause of the problem. I removed the offending character and the error disappeared.

How do I get the PATH of a file that is in a known folder with a known extension, but with an unknown filename?

i'm working with an app for iOS, using an external framework for downloading an image. The file is saved in a known director inside documents directory, but the filename is unknown. Is an image, of a known extension. How can i get the filename or filepath? any idea?
thanks.
You can enumerate each file and check its extension
NSDirectoryEnumerator* myFolderDir = [manager enumeratorAtPath:myfolder];
for (id file in myFolderDir)
{
NSLog(#" file %#",file);
if ([[file pathExtension] isEqualToString:#"YOUREXTENSION"])
{
NSString *path = [myfolder stringByAppendingPathComponent:file];
[self.Files addObject:path];
}
}
Just iterate contents of your directory.
NSString *directoryPath = #"your directory path";
NSString *extension = #"your extension";
NSError *error = nil;
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:&error];
if(!error) {
for(NSString *item in directoryContent) {
if([item rangeOfString:extension].location != NSNotFound) {
// item is filename at directory path with current extension
}
}
}

Renaming and moving file using NSFIleManager

This is my code to rename and move file from a temporary directory to My Documents directory.
So the problem is within two sections of mode Create a Directory and Attempt to move. The rest all is working correctly..
When I comment out the Create directory section, the Attempt to Move section logs in the console:
Unable to Move the File..Error Code 4.
Now I researched error code 4 and it means that the directory does not exist. So I added the code to create the directory.
Now when I run the program the directory is created but the Attempt to Move section logs:
Unable to Move File..error code 512
Now researching on it it is due to the file already exists. The destination must not exist.
So I am pretty confused, since both error codes are contracting each other.
{
NSError *error;
NSFileManager* manager = [[NSFileManager alloc] init];
NSString* tempFile =[NSTemporaryDirectory() stringByAppendingPathComponent:#"recordTest.caf"];
if (tempFile)
{
// Get the Documents Directory
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSLog(#"Documents directory: %#",
[manager contentsOfDirectoryAtPath:documentsDirectory error:&error]);
//Get the User File Save Name from the text field
NSString *UserText = [[self FileNameText] text];
// Rename the file, by moving the file
NSString *filePath2 = [documentsDirectory
stringByAppendingPathComponent:[NSString stringWithString:UserText]];
// Create a Directory
if( [manager createDirectoryAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,UserText] withIntermediateDirectories:NO attributes:nil error:&error]!= YES)
{
NSLog(#"Directory error");
}
if([manager fileExistsAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,UserText]])
{
NSLog(#"Path exist");
NSLog(#"Documents directory: %#",
[manager contentsOfDirectoryAtPath:documentsDirectory error:&error]);
}
// Attempt the move
if ([manager moveItemAtPath:tempFile toPath:filePath2 error:&error] != YES)
{
NSLog(#"Unable to move file: %#", [error localizedDescription]);
}
else
{
if ([manager removeItemAtPath:tempFile error:&error] != YES)
NSLog(#"Unable to delete file: %#", [error localizedDescription]);
}
}
[manager release];
}
The problem is most likely that the file you are trying to move doesn't exist.
replace
if (tempFile) //this will return YES every time, telling you you have a string!
with
if ([manager fileExistsAtPath:tempFile]) //this will tell you if the file exists at that path
A few notes
1. To see with your eyes if the file you are looking for really exists, check the simulator application folders at something similar to this:
/Users/yogevshelly/Library/Application\ Support/iPhone\
Simulator/5.0/Applications
then browse to a specific application
2. Don't just append strings to get folders , do something like this:
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [dirPaths objectAtIndex:0];
3. The following line will create a folder with the file's name as the folders name!:
[manager createDirectoryAtPath:filePath2 withIntermediateDirectories:NO attributes:nil error:&error]
creating a folder from a filename seems weird, what you want to do is either copy the file to an existing directory or first create a directory and copy the file into-it
you use the metod
contentsOfDirectoryAtPath: withIntermediateDirectories: attributes:error
this method create directory but you pass it the filename.
i think you create /Documents/filename/ instead of /Documents/filename
As per my understanding the problem part of the code is following one
// Create a Directory
if( [manager createDirectoryAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,UserText] withIntermediateDirectories:NO attributes:nil error:&error]!= YES)
{
NSLog(#"Directory error");
}
You are creating a folder in with the file name in same location .... try commenting the the above code .. it should work.

Array of NSStrings from filenames within a folder?

I'm trying to create an array of NSStrings of the contents of a folder that I've dragged into my project... but when I count the items in the array afterwards, it's always comes back with 0;
So, my folder in my project looks like this
-Cards
-Colors
Blue.png
Green.png
Orange.png
Yellow.png
Purple.png
Black.png
And my code which tries to get this list of files (the color pngs) is
NSError *error = nil;
NSString *pathString = [[NSString alloc] init];
pathString = [[NSString alloc] initWithString:#"/Cards/Colors/"];
NSArray *fileList = [[NSArray alloc] init];
fileList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pathString error: &error];
[pathString release];
NSLog(#"%#", error);
// this is always 0
NSLog(#"file list has %i items", [fileList count]);
The NSError I get is
Error Domain=NSCocoaErrorDomain Code=260 "The operation couldn’t be completed. (Cocoa error 260.)" UserInfo=0x596db00 {NSUserStringVariant=(
Folder
), NSFilePath=/Cards/Color/, NSUnderlyingError=0x5925ef0 "The operation couldn’t be completed. No such file or directory"}
Any ideads where I am going wrong?
You're initializing pathString to the absolute path /Cards/Colors/. This path is a system-wide path, so on the iPhone, far outside your app's sandbox.
Try this instead:
NSString *pathString = [[NSBundle mainBundle] pathForResource:#"Cards/Colors" ofType:nil];
NSArray *fileList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pathString error: &error];
(Note that the way you have your code in the question, you alloc/init fileList, then immediately leak the object by assigning to it the results of contentsOfDirectoryAtPath:error:. This is a bug.)

How to force coredata to rebuild sqlite database model?

In my app I sometimes need to rebuild and repopulate database file. SQLite databse is created and managed by CoreData stack.
What I'm trying to do is drop the file and then simply recreate persistentStoreCoordinator object.
It works under simulator but not on device, where I'm getting such an error:
NSFilePath = "/var/mobile/Applications/936C6CC7-423A-46F4-ADC0-7184EAB0CADD/Documents/MYDB.sqlite";
NSUnderlyingException = I/O error for database at /var/mobile/Applications/936C6CC7-423A-46F4-ADC0-7184EAB0CADD/Documents/MYDB.sqlite. SQLite error code:1, 'table ZXXXX already exists';
I cannot find the cause of this in any way. It indicates two different problems - Cocoa error 256 indicates that file does not exist or is not readable. But file IS created after creating persistenStoreCoordinator, although it's empty, but after executing some queries it disappears.
Second message indicating attempt to create alredy existing table is quite strange in that case.
I'm quite confused and cannot get the point what's going on here. My code looks like this:
NSString *path = [[WLLocalService dataStorePath] relativePath];
NSError *error = nil;
WLLOG(#"About to remove file %#", path);
[[NSFileManager defaultManager] removeItemAtPath: path error: &error];
if (error != nil) {
WLLOG(#"Error removing the DB: %#", error);
}
[self persistentStoreCoordinator];
WLLOG(#"Rebuild DB result %d", [[NSFileManager defaultManager] fileExistsAtPath: path]);
After this code is exectued, DB file exists but is empty. When then first query (and all following) is executed, it gives me the error above and file disappears.
Does anybody has an idea what's wrong with it?
Big thanks for pointing me the right way!
The Core Data stack does not like you removing the file under it. If you are wanting to delete the file you should tear down the stack, delete the file and then reconstruct the stack. That will eliminate the issue.
Part of the problem is that the stack keeps a cache of the data that is in the file. When you remove the file you don't have a way to clear that cache and you are then putting Core Data into an unknown and unstable state.
You can try telling the NSPersistentStoreCoordinator you are removing the file with a call to -removePersistentStore:error: and then adding the new store with a call to -addPersistentStoreWithType:configuration:URL:options:error:. I am doing that currently in ZSync and it works just fine.
I use the following method -resetApplicationModel in my app delegate and it works fine for me.
You may not need the kApplicationIsFirstTimeRunKey user default, but I use it to test whether to populate the Core Data store with default settings in a custom method called -setupModelDefaults, which I also call from -applicationDidFinishLaunching: if the first-time run flag is YES.
- (BOOL) resetApplicationModel {
// ----------------------
// This method removes all traces of the Core Data store and then resets the application defaults
// ----------------------
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:kApplicationIsFirstTimeRunKey];
NSLog(#"Turned ON the first-time run flag...");
NSError *_error = nil;
NSURL *_storeURL = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"MyAppSQLStore.sqlite"]];
NSPersistentStore *_store = [persistentStoreCoordinator persistentStoreForURL:_storeURL];
//
// Remove the SQL store and the file associated with it
//
if ([persistentStoreCoordinator removePersistentStore:_store error:&_error]) {
[[NSFileManager defaultManager] removeItemAtPath:_storeURL.path error:&_error];
}
if (_error) {
NSLog(#"Failed to remove persistent store: %#", [_error localizedDescription]);
NSArray *_detailedErrors = [[_error userInfo] objectForKey:NSDetailedErrorsKey];
if (_detailedErrors != nil && [_detailedErrors count] > 0) {
for (NSError *_detailedError in _detailedErrors) {
NSLog(#" DetailedError: %#", [_detailedError userInfo]);
}
}
else {
NSLog(#" %#", [_error userInfo]);
}
return NO;
}
[persistentStoreCoordinator release], persistentStoreCoordinator = nil;
[managedObjectContext release], managedObjectContext = nil;
//
// Rebuild the application's managed object context
//
[self managedObjectContext];
//
// Repopulate Core Data defaults
//
[self setupModelDefaults];
return YES;
}
You can keep a "clean" copy of your sqlite database as part of the application bundle, then just copy over the version in the documents directory whenever you'd like to refresh the database.
Here's some code from an App that does something similar (although this version will not copy over and existing db):
// Check for the existence of the seed database
// Get the path to the documents directory and append the databaseName
NSString* databasePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: kDatabaseName];
NSFileManager* fileManager = [NSFileManager defaultManager];
if ( ![fileManager fileExistsAtPath: databasePath] )
{
NSString* databasePathFromApp = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent: kDatabaseName];
[fileManager copyItemAtPath: databasePathFromApp
toPath: databasePath
error: nil];
}
[fileManager release];