Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

troop231

macrumors 603
Original poster
Jan 20, 2010
5,822
553
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"

Code:
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);
        }
    }
}
 
Last edited:

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
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"

Code:
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

macrumors 603
Original poster
Jan 20, 2010
5,822
553
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:

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

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
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:

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

macrumors 603
Original poster
Jan 20, 2010
5,822
553
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

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
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

macrumors 603
Original poster
Jan 20, 2010
5,822
553
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:

Code:
    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

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
Here is the code that solved it:

Code:
    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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.