NSString вызывает сбой моего приложения ... возможно - PullRequest
1 голос
/ 20 октября 2011

Огромная и странная проблема: Я делаю снимки и сохраняю их в своем приложении с именем, которое я выбрал (день + случайное число), и сохраняю адрес картинки в моей переменной NSString "imagePath". До конца этого метода я могу получить доступ к содержимому imagePath, который является глобальной переменной; но когда я пытаюсь использовать его в другом методе, я должен сохранить этот адрес в базе данных sqlite, он дает мне EXC_BAD_ACCESS. Хорошо, также, если я пытаюсь увидеть его содержимое с помощью "NSLog (@"% @ ", imagePath);" это терпит крах. Некоторые идеи?

-(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;
}

Ответы [ 6 ]

2 голосов
/ 20 октября 2011

Проблема в том, что это:

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

присваивает imagePath автоматически выпущенному объекту. Это означает, что он будет выпущен как часть NSAutoreleasePool утечки, которая происходит в конце цикла цикла событий.

Поскольку вы не создаете память , но хотите, чтобы она зависла вокруг , вам необходимо retain it:

[imagePath retain];

Вам необходимо определить, когда этот фрагмент сохраненной памяти может быть освобожден . Поскольку мы не знаем точно, как работает ваше приложение, решение остается за вами. Если вы вызываете этот метод более одного раза, вы, вероятно, захотите выпустить его так:

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

Если этот объект должен выжить только до тех пор, пока ваш контроллер выбора, вы должны освободить его методом dealloc:

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

В противном случае, если это сохранится в течение всего срока службы вашего приложения, не беспокойтесь о выпуске его в dealloc. (Но вы все равно должны освободить его до назначения, если вы назначаете его более одного раза.) Память будет возвращена ОС после завершения работы приложения.

1 голос
/ 20 октября 2011

Установить NSZombieEnabled , MallocStackLogging и guard malloc в отладчике.Затем, когда произойдет сбой вашего приложения, введите в консоли gdb:

(gdb) info malloc-history 0x543216

Замените 0x543216 адресом объекта, вызвавшего сбой, и вы получите гораздо более полезную трассировку стека,должно помочь вам точно определить строку кода, которая вызывает проблему.

См. эту статью для получения более подробных инструкций.

1 голос
/ 20 октября 2011

Вы можете попробовать это ...

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

[imagePath retain];

// Your code//

[webData writeToFile:imagePath atomically:YES];
NSLog(@"%@", imagePath);

[imagePath release];
0 голосов
/ 20 октября 2011

, поскольку imagePath является глобальной переменной.затем вы можете получить к нему доступ из любого места в классе, но что происходит, когда вы сохраняете какое-то значение в это время, вы его не сохраняете.поэтому используйте retain для него.

после этой строки

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

[imagePath retain];

и освободите его в dealloc, но не в каком-либо методе, пока вы не вызываете retain в любое другое время.

0 голосов
/ 20 октября 2011

Значение, которое вы храните в imagePath, не принадлежит вам.С stringByAppendingPathComponent: вы получаете автоматически выпущенный объект.Вы сохранили это.(Кстати: вы разрабатываете под ios5?)

0 голосов
/ 20 октября 2011
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
   NSString *imgPathWithOutDir = [[NSString alloc] initWithFormat:@" %@.png", photoName];
    imagePath = [documentsDirectory stringByAppendingPathComponent:imgPathWithOutDir];

    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);
    [imgPathWithOutDir release];
    imgPicker = nil;
...