PDA

View Full Version : [Resolved] How to move all files from NSDocumentDirectory to NSCachesDirectory?




troop231
Aug 23, 2012, 07:59 PM
Hello,

I'm trying to move all of the documents that reside in the NSDocumentDirectory to the NSCachesDirectory, and then delete all of those NSDocument files upon the first app launch of my next version update to my app. The only reason I'm doing this is to abide by Apple's iOS data storage guidelines, as my app update was rejected for saving .PDF files to the NSDocumentsDirectory (I have no clue why, because the app has never been rejected for this until this update (app is almost 2 years old, and I have been saving .PDFs this way since day 1), maybe I got a strict reviewer?)

I need to move all of the user's already downloaded .PDF files to the NSCachesDirectory and then delete them from the NSDocumentDirectory.

Is there a simple way this can be accomplished?

Thank you in advance for any help provided.

This is my code, but am getting this error in the Console: NSFilePath=Test.pdf, NSDestinationFilePath=/Users/Charley/Library/Application Support/iPhone Simulator/5.1/Applications/96EB01D1-81B7-4ECE-B337-D2D663969EE3/Library/Caches, NSUnderlyingError=0xb566d50 "The operation couldn’t be completed. File exists"

NSFileManager *fileManager = [NSFileManager defaultManager];

NSError *error;
NSUserDefaults *Defaults;
int launchCount;

Defaults = [NSUserDefaults standardUserDefaults];
launchCount = [Defaults integerForKey:@"launchCount" ] + 1;
[Defaults setInteger:launchCount forKey:@"launchCount"];
[Defaults synchronize];

if(launchCount == 1) {

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

NSArray *path2 = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *dest = [path2 objectAtIndex:0];

NSArray *Contents = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:&error];

for(NSString *source in Contents)
{
if(![fileManager moveItemAtPath:source
toPath:dest
error:&error])
{
NSLog(@"Error: %@", error);
}
}
}



Duncan C
Aug 23, 2012, 08:32 PM
Hello,

I'm trying to move all of the documents that reside in the NSDocumentDirectory to the NSCachesDirectory, and then delete all of those NSDocument files upon the first app launch of my next version update to my app. The only reason I'm doing this is to abide by Apple's iOS data storage guidelines, as my app update was rejected for saving .PDF files to the NSDocumentsDirectory (I have no clue why, because the app has never been rejected for this until this update (app is almost 2 years old, and I have been saving .PDFs this way since day 1), maybe I got a strict reviewer?)

I need to move all of the user's already downloaded .PDF files to the NSCachesDirectory and then delete them from the NSDocumentDirectory.

Is there a simple way this can be accomplished?

Thank you in advance for any help provided.

This is my code, but am getting this error in the Console: NSFilePath=Test.pdf, NSDestinationFilePath=/Users/Charley/Library/Application Support/iPhone Simulator/5.1/Applications/96EB01D1-81B7-4ECE-B337-D2D663969EE3/Library/Caches, NSUnderlyingError=0xb566d50 "The operation couldn’t be completed. File exists"

NSFileManager *fileManager = [NSFileManager defaultManager];

NSError *error;
NSUserDefaults *Defaults;
int launchCount;

Defaults = [NSUserDefaults standardUserDefaults];
launchCount = [Defaults integerForKey:@"launchCount" ] + 1;
[Defaults setInteger:launchCount forKey:@"launchCount"];
[Defaults synchronize];

if(launchCount == 1) {

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

NSArray *path2 = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *dest = [path2 objectAtIndex:0];

NSArray *Contents = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:&error];

for(NSString *source in Contents)
{
if(![fileManager moveItemAtPath:source
toPath:dest
error:&error])
{
NSLog(@"Error: %@", error);
}
}
}



Look carefully at what your code is doing. You build a path "documentsDirectory". Then you build a path to the cashes directory and call it "dest". (That's the path to the caches directory, not to the files in the caches directory)

Then you loop through each file in the documents directory, trying to write every one of those files to the path to the caches directory (not a path to a file in the caches directory, but to the caches directory itself.)

You need to extract the filename from each source file and build a destination pathname by combining that with the path to the caches directory. Take a look at the NSString methods lastPathComponent and stringByAppendingPathComponent.

troop231
Aug 23, 2012, 08:48 PM
Look carefully at what your code is doing. You build a path "documentsDirectory". Then you build a path to the cashes directory and call it "dest". (That's the path to the caches directory, not to the files in the caches directory)

Then you loop through each file in the documents directory, trying to write every one of those files to the path to the caches directory (not a path to a file in the caches directory, but to the caches directory itself.)

You need to extract the filename from each source file and build a destination pathname by combining that with the path to the caches directory. Take a look at the NSString methods lastPathComponent and stringByAppendingPathComponent.

Hello Duncan, I got a few steps closer with my updated code below, but I am now getting this error in the Console: NSFilePath=Test.pdf, NSDestinationFilePath=/Users/Charley/Library/Application Support/iPhone Simulator/5.1/Applications/96EB01D1-81B7-4ECE-B337-D2D663969EE3/Library/Caches/Test.pdf, NSUnderlyingError=0x6b7b080 "The operation couldn’t be completed. No such file or directory"

Code:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

NSArray *path2 = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

NSString *newDirectory = [path2 objectAtIndex:0];

NSArray *Contents = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:&error];

for(NSString *source in Contents)
{
NSString *dest = [newDirectory stringByAppendingPathComponent:
[source lastPathComponent]];

if(![fileManager moveItemAtPath:source
toPath:dest
error:&error])
{
NSLog(@"Error: %@", error);
}
}
}


I appreciate your response.

Duncan C
Aug 23, 2012, 09:47 PM
Hello Duncan, I got a few steps closer with my updated code below, but I am now getting this error in the Console: NSFilePath=Test.pdf, NSDestinationFilePath=/Users/Charley/Library/Application Support/iPhone Simulator/5.1/Applications/96EB01D1-81B7-4ECE-B337-D2D663969EE3/Library/Caches/Test.pdf, NSUnderlyingError=0x6b7b080 "The operation couldn’t be completed. No such file or directory"

Code:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

NSArray *path2 = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

NSString *newDirectory = [path2 objectAtIndex:0];

NSArray *Contents = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:&error];

for(NSString *source in Contents)
{
NSString *dest = [newDirectory stringByAppendingPathComponent:
[source lastPathComponent]];

if(![fileManager moveItemAtPath:source
toPath:dest
error:&error])
{
NSLog(@"Error: %@", error);
}
}
}


I appreciate your response.

Log both the source and dest paths and see if you can figure out what's happening. If you run on the simulator, you can copy the paths strings and then try pasting them into a file open dialog in Mac a Mac OS app like TextEdit, Photoshop, etc. (using command option G to bring up the "Go to folder" sheet.)

troop231
Aug 23, 2012, 09:55 PM
Log both the source and dest paths and see if you can figure out what's happening. If you run on the simulator, you can copy the paths strings and then try pasting them into a file open dialog in Mac a Mac OS app like TextEdit, Photoshop, etc. (using command option G to bring up the "Go to folder" sheet.)

Got it! I logged the source path, and all the console shows is this: Test.pdf

Obviously that wont work right? I'm wondering how I can solve it. It seems as if all its grabbing is the file name, but it cant find the relative path of the file to actually move it to the destination path, which was logged to the console correctly: /Users/Charley/Library/Application Support/iPhone Simulator/5.1/Applications/96EB01D1-81B7-4ECE-B337-D2D663969EE3/Library/Caches/Test.pdf

This has me stumped!

Duncan C
Aug 24, 2012, 07:04 AM
Got it! I logged the source path, and all the console shows is this: Test.pdf

Obviously that wont work right? I'm wondering how I can solve it. It seems as if all its grabbing is the file name, but it cant find the relative path of the file to actually move it to the destination path, which was logged to the console correctly: /Users/Charley/Library/Application Support/iPhone Simulator/5.1/Applications/96EB01D1-81B7-4ECE-B337-D2D663969EE3/Library/Caches/Test.pdf

This has me stumped!

It's been a while since I've used NSFileManager, and I don't remember if contentsOfDirectoryAtPath is supposed to return filenames or full paths. Sounds like it returns just filenames. In that case you need to build the source path for the copy just like you're building the dest path.

troop231
Aug 24, 2012, 11:22 AM
It's been a while since I've used NSFileManager, and I don't remember if contentsOfDirectoryAtPath is supposed to return filenames or full paths. Sounds like it returns just filenames. In that case you need to build the source path for the copy just like you're building the dest path.

Here is the code that solved it:


NSError *error = nil;
NSUserDefaults *Defaults;
int launchCount;

Defaults = [NSUserDefaults standardUserDefaults];
launchCount = [Defaults integerForKey:@"launchCount" ] + 1;
[Defaults setInteger:launchCount forKey:@"launchCount"];
[Defaults synchronize];

if(launchCount == 1) {

NSString *source = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

NSString *destination = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

NSArray *contents = [fileManager contentsOfDirectoryAtPath:source error:&error];

for(NSString *sourceFileName in contents)
{
NSString *sourceFile = [sourceDirectory stringByAppendingPathComponent:sourceFileName];
NSString *destFile = [destinationDirectory stringByAppendingPathComponent:sourceFileName];

if(![fileManager moveItemAtPath:sourceFile toPath:destFile error:&error])
{
NSLog(@"Error: %@", error);
}
}
}

Duncan C
Aug 25, 2012, 09:42 AM
Here is the code that solved it:


NSError *error = nil;
NSUserDefaults *Defaults;
int launchCount;

Defaults = [NSUserDefaults standardUserDefaults];
launchCount = [Defaults integerForKey:@"launchCount" ] + 1;
[Defaults setInteger:launchCount forKey:@"launchCount"];
[Defaults synchronize];

if(launchCount == 1) {

NSString *source = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

NSString *destination = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

NSArray *contents = [fileManager contentsOfDirectoryAtPath:source error:&error];

for(NSString *sourceFileName in contents)
{
NSString *sourceFile = [sourceDirectory stringByAppendingPathComponent:sourceFileName];
NSString *destFile = [destinationDirectory stringByAppendingPathComponent:sourceFileName];

if(![fileManager moveItemAtPath:sourceFile toPath:destFile error:&error])
{
NSLog(@"Error: %@", error);
}
}
}


Yup, that looks like it should work. I'd suggest using clearer names, like sourceDir and destDir for the directory names, and sourcePath and destPath for the fully qualified pathnames. That makes your code more self-documenting.