views:

843

answers:

2

So I'm kind of a Cocoa n00b, but I'm writing this simple little program and I can't get the NSFileManager delegate method "shouldProceedAfterError..." to fire. Here's the code I'm running in my AppDelegate

-(BOOL)copyFile {
    [[NSFileManager defaultManager] setDelegate:self];

    NSError *copyError = nil;
    NSString *filename = [[NSString alloc] initWithString:[[[self.sourceFile path] componentsSeparatedByString:@"/"] lastObject]];
    NSString *destination = [[[[[UserData sharedData] folderLocation] path] stringByAppendingString:@"/"] stringByAppendingString:filename];

    [[NSFileManager defaultManager] copyItemAtPath:[self.sourceFile path] toPath:destination error:&copyError];

    NSLog(@"error! %@",copyError);

    [filename release];
    return YES;
}

- (BOOL)fileManager:(NSFileManager *)fileManager shouldProceedAfterError:(NSError *)error copyingItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath {
    NSLog(@"more error... %@",error);
    return NO;
}
- (BOOL)fileManager:(NSFileManager *)fileManager shouldCopyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath {
    NSLog(@"in shouldCopyItemAtPath...");
    return YES;
}

The situation I'm trying to deal with is if the file already exists at the destination. I do get an error, but I never get that "more error..." trace to output. I also DO get that trace from shouldCopyItemAtPath: so I'm not exactly sure why the method isn't firing?

Am I going crazy, how did I mess up the delegate implementation here? Thanks for any help!

A: 

This is just a hypothesis, but since copyItemAtPath:toPath:error is defined such that "The file specified in srcPath must exist, while dstPath must not exist prior to the operation.", perhaps the scenario where dstPath already exists isn't considered an "error," and so doesn't fire the delegate.

i.e. perhaps "It's not an error if you do something we told you not to do."

You can always do the check and delete it yourself:

NSFileManager* fileManager = [NSFileManager defaultManager];

// Delete the file if it already exists.
if ([fileManager fileExistsAtPath: destination])
        if (![fileManager removeItemAtPath: destination error: error])
                return NO;

return [fileManager copyItemAtPath: source toPath: destination error: error];
Dewayne Christensen
"It's not an error if you do something we told you not to do."doh. I must've totally missed that part. I was hoping I could implement some kind of modal window in the delegate method, but you're right I just need to check before I start the copy. Thanks for the response! I'd vote up but I don't have any rep :(
Chief
A: 

Probably you are providing a wrong path as source?
copyItemAtPath does not call the delegate methods if the the source path is invalid.
You can test that if you use the following method:

-(IBAction)copyFile:(id)sender
{
    [[NSFileManager defaultManager] setDelegate:self];
    NSError* copyError = nil;
    NSString* sourceFilepath = [@"~/Desktop/source.txt" stringByExpandingTildeInPath];
    NSString* targetFilepath = [@"~/Desktop/target.txt" stringByExpandingTildeInPath];  
    [[NSFileManager defaultManager] copyItemAtPath:sourceFilepath toPath:targetFilepath error:&copyError];  
    NSLog(@"Error:%@", copyError);  
}

When calling that method I notice the following behavior:

  • If ~/Desktop/source.txt is a file and ~/Desktop/target.txt does not exist:
    • NSFileManager calls the shouldCopyItemAtPath delegate method
  • If ~/Desktop/source.txt is a file and ~/Desktop/target.txt exists:
    • NSFileManager first calls the shouldCopyItemAtPath and shouldProceedAfterError
  • If ~/Desktop/source.txt does not exist
    • NSFileManager does not call any delegate method and just returns a NSError objet
weichsel