Search code examples
objective-cxcodenssavepanel

NSSavePanel issues


I am semi-new to cocoa programming, however I have worked quite a bit in C++;

I am having some issues with the NSSavePanel class. Whenever I use it (as shown below), I can see (by using breakpoints) that the code tries to execute the ending bracket. I then get a BAD_ACCESS message from Xcode in the main.h file. I cannot for the life of me figure out what I am doing wrong. Here is the code:

- (void)scannerDevice:(ICScannerDevice*)scanner didCompleteScanWithError:(NSError*)error;
{
    NSLog( @"scannerDevice: \n%@\ndidCompleteScanWithError: \n%@\n", scanner, error );
    [mProgressIndicator setHidden:YES];

    NSSavePanel *savePopup = [[NSSavePanel alloc]init];
    [savePopup runModal];

    NSMutableString *saveString = [[NSString alloc] init];
    saveString = [[savePopup URL] absoluteString];
    [saveString deleteCharactersInRange:NSMakeRange(0, 16)];
    [saveString appendString:@".jpeg"];

    NSLog(@"[[ADDRESS: %@", saveString); //Outputs /Users/tannerdsilva/Documents/TestFolder/NewName.jpeg
    NSError *errorSave = [[NSError alloc] init];

    [manager moveItemAtPath:[@"~/Foo.jpeg" stringByExpandingTildeInPath] toPath:[[savePopup URL] absoluteString] error:&errorSave]; // ~/Foo.jpeg does exist

    NSLog(@"ERROR: %@", errorSave);
    [saveString dealloc];
    [savePopup dealloc];

}

When I hard code the new destination and remove the NSSavePanel, I don't get any crashes.

Thank you ahead of time, and I apologize if this is a simple fix.


Solution

  • There are a couple of issues with your code.

    • You declare saveString as an NSMutableString but initialize it as an (immutable) NSString.
    • You're then not using that string at all but replace it with the autoreleased (and immutable) NSString that's returned from absoluteString, causing the original string to leak.
    • NSString responds to neither deleteCharactersInRange: nor to appendString (those are methods of NSMutableString).
    • You're leaking errorSave which you should initialize as nil anyway.
    • You should never ever call dealloc yourself, use release instead. But don't release saveString because it's already autoreleased (see above), you're over-releasing it here which will cause a crash when the autorelease pool is drained.