Search code examples
iphoneobjective-cnsstringnslog

NSString makes my app crash... maybe


Huge and strange problem: I take pictures and save them inside my app with a name I decided (day+random number), and I store the address of the picture in my "imagePath" NSString variable. Till the end of this method i can access the content of "imagePath, which is a global variable; but when I try to use it in another method, I should save this address in a sqlite database, it give me EXC_BAD_ACCESS. Well, also if I try to see its content with "NSLog(@"%@",imagePath);" it crashs. Some ideas?

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissModalViewControllerAnimated:YES];

    int r = arc4random() % 9999;
    NSDate *date = [NSDate date];
    NSString *photoName = [dateNameFormatter stringFromDate:date];
    photoName = [photoName stringByAppendingString:[NSString stringWithFormat:@"%d", r]];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    imagePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@" %@.png", photoName]];

    UIImage *picture = [info objectForKey:UIImagePickerControllerOriginalImage];

    // ----- CODE FOR SCALE THE IMAGE ----- //

    // ----- ----- - END CODE - ----- ----- //

    NSData *webData = UIImagePNGRepresentation(picture);
    CGImageRelease([picture CGImage]);
    [webData writeToFile:imagePath atomically:YES];
    NSLog(@"%@", imagePath);
    imgPicker = nil;
}

Solution

  • The problem is that this:

    imagePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@" %@.png", photoName]];
    

    assigns imagePath to an autoreleased object. This means that it will be released as part of the NSAutoreleasePool drain that occurs at the end of the cycle of the event loop.

    Since you don't create the memory but you want it to hang around, you have to retain it:

    [imagePath retain];
    

    What you need to determine is when this piece of retained memory can be released. Since we don't know exactly how your app works, the decision is up to you. If you're calling this method more than once, you'll probably want to release it as such:

    if (imagePath) {
        [imagePath release];
    }
    imagePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@" %@.png", photoName]];
    [imagePath retain];
    

    If this object should only survive as long as your picker controller, you should release it in the dealloc method:

    - (void)dealloc {
        [imagePath release];
        // Other releases
        [super dealloc];
    }
    

    Otherwise, if this should survive for the lifetime of your application, don't worry about releasing it in dealloc. (But you should still release it prior to assigning it, if you're assigning it more than once.) The memory will be reclaimed by the OS when your application terminates.