EXC_BAD_ACCESS в конце метода - PullRequest
       3

EXC_BAD_ACCESS в конце метода

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

В этом методе я добавляю содержимое UITextFields, изображений и других строк в базу данных sqlite.Все отлично работаетЯ имею в виду, когда я нажимаю кнопку «Добавить», появляется изображение «ОК», воспроизводится звук и все содержимое добавляется в базу данных (я могу проверить перезапуск приложения).Но после всего этого у меня есть эта ошибка в "main.m"

Это метод:

-(IBAction)addItem:(id)sender { //gestione pulsante aggiunta elemento
    if (([itemNameField.text length] == 0) || ([priceField.text length] == 0) || ([priceField.text doubleValue] == 0.0) || ((incomeOutcome.selectedSegmentIndex != 0) && (incomeOutcome.selectedSegmentIndex != 1))) {
        if ([itemNameField.text length] == 0) {
        statusLabel.text = [[NSString alloc] initWithFormat: @"Specificare un nome."];
        } else if (([priceField.text length] == 0) || ([priceField.text doubleValue] == 0.0)) {
            statusLabel.text = [[NSString alloc] initWithFormat: @"Specificare un prezzo."];
        } else if ((incomeOutcome.selectedSegmentIndex != 0) && (incomeOutcome.selectedSegmentIndex != 1)) {
            statusLabel.text = [[NSString alloc] initWithFormat: @"Specificare \"Income/Outcome\" ."];            
        }
        if (!categoriaLabel.hidden) {
            [self hideThemAll];
        }
        [incomeOutcome setSelectedSegmentIndex:-1];
        statusLabel.hidden = NO;
        error = true;
        [self playSound];
        [ok setImage:[UIImage imageNamed:@"error.png"]];
        ok.hidden = NO;
        return;
    }
    //apriamo il database
    sqlite3 *db;
    int dbrc; //Codice di ritorno del database (database return code)
    iWalletAppDelegate *appDelegate = (iWalletAppDelegate*) [UIApplication sharedApplication].delegate;
    const char *dbFilePathUTF8 = [appDelegate.dbFilePath UTF8String];
    dbrc = sqlite3_open(dbFilePathUTF8, &db);
    if (dbrc) {
        NSLog(@"Impossibile aprire il Database!");
        return;
    }
    //database aperto! Inseriamo valori nel database.
    sqlite3_stmt *dbps; //Istruzione di preparazione del database
    NSString *insertStatementsNS;
    if (incomeOutcome.selectedSegmentIndex == 0) {
        insertStatementsNS = [NSString stringWithFormat: @"insert into \"shoppinglist\" (item, price, groupid, incout, path,  dateadded) values (\"%@\", \"%@\", \"Entrata\", %d, \"%@\", DATETIME('NOW'))", itemNameField.text, priceField.text, incomeOutcome.selectedSegmentIndex, imagePath];
    } else if ([categoryNameField.text length] != 0) { 
        insertStatementsNS = [NSString stringWithFormat: @"insert into \"shoppinglist\" (item, price, groupid, incout, path, dateadded) values (\"%@\", \"%@\", \"%@\", %d, \"%@\", DATETIME('NOW'))", itemNameField.text, priceField.text, categoryNameField.text, incomeOutcome.selectedSegmentIndex, imagePath]; 
    } else { 
        insertStatementsNS = [NSString stringWithFormat: @"insert into \"shoppinglist\" (item, price, groupid, incout, path, dateadded) values (\"%@\", \"%@\", \"Varie\", %d, \"%@\", DATETIME('NOW'))", itemNameField.text, priceField.text, incomeOutcome.selectedSegmentIndex, imagePath];
    }
    const char *insertStatement = [insertStatementsNS UTF8String];
    dbrc = sqlite3_prepare_v2(db, insertStatement, -1, &dbps, NULL);
    dbrc = sqlite3_step(dbps);

    //faccio pulizia rilasciando i database
    sqlite3_finalize(dbps);
    sqlite3_close(db);

    // Pulisci i campi e indica successo nello status
    statusLabel.hidden = NO;
    statusLabel.text = [[NSString alloc] initWithFormat: @"Aggiunto %@", itemNameField.text];

    itemNameField.text = @"";
    priceField.text = @"";
    categoryNameField.text = @"";
    imagePath = @"";
    [incomeOutcome setSelectedSegmentIndex:-1];
    error = false;
    [self hideThemAll];
    [self playSound];
    [ok setImage:[UIImage imageNamed:@"ok.png"]];
    ok.hidden = NO;
    nome = @"";
    prezzo =@"";
    [photoPreview setImage:[UIImage imageNamed:@"noPhoto.png"]];
    [[self parentViewController]dismissModalViewControllerAnimated:YES];
}    

РЕДАКТИРОВАТЬ

Благодаря Исааку я (возможно) обнаружил проблему: я не сохранял изображение, снятое с камеры.

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

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

    UIImage *picture = [info objectForKey:UIImagePickerControllerOriginalImage];

    // ----- CODE FOR SCALE THE IMAGE ----- //
    if (picture.size.width == 1936) {
        picture = [picture scaleToSize:CGSizeMake(480.0f, 720.0f)];
    } else {
        picture = [picture scaleToSize:CGSizeMake(720.0f, 480.0f)];
    }

    photoPreview.image =  picture;

    photoPreview.contentMode = UIViewContentModeScaleAspectFit;

    CGRect frame = photoPreview.frame;
    if (picture.size.width == 480) {
        frame.size.width = 111.3;
        frame.size.height =167;
    } else {
        frame.size.width = 167;
        frame.size.height =111.3;
    }
    photoPreview.frame = frame;
    // ----- ----- - END CODE - ----- ----- //    

    NSData *webData = UIImagePNGRepresentation(picture);
    CGImageRelease([picture CGImage]);
    [webData writeToFile:imagePath atomically:YES];
    [picture retain]; // <-- This little thing here!
    //imgPicker = nil;
}

Теперь это работает!Но если вы видите другие проблемы, пожалуйста, дайте мне их заметить.

Ответы [ 3 ]

4 голосов
/ 21 октября 2011

Нет оснований для создания NSString, например:

 statusLabel.text = [[NSString alloc] initWithFormat: @"Specificare un nome."];

Просто напишите

statusLabel.text = @"Specificare un nome.";

Возможно, это не причина EXC_BAD_ACCESS, но, по крайней мере, вы можете избежать нескольких утечек памяти.

3 голосов
/ 21 октября 2011

Обычно EXC_BAD_ACCESS возникает, когда вы пытаетесь получить доступ к памяти, которая была освобождена.В вашем примере кода я не вижу вызовов [освобождения объекта] (это совсем другая проблема, если только вы не используете ARC).Но я предполагаю, что эта ошибка является результатом вызова, который делается вне области действия этого метода - что-то освобождается преждевременно.

Вы можете вставить весь свой класс или рассмотреть возможность использования инструмента Инструменты "Зомби", чтобы определить висящий указатель, который (вероятно) вызывает это.

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

На мой взгляд, Исаак прав. Я просто хочу добавить одну догадку. Скорее всего ошибка возникает при вызове

[[self parentViewController]dismissModalViewControllerAnimated:YES];

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

Вы можете довольно легко обнаружить это только с помощью точек останова.

...