Вопрос по iphone – UIAlertView не отображается и приводит к ошибке «EXC_BAD_ACCESS»

3

Метод вызывается при нажатии кнопки возврата на клавиатуре. После вызова другого метода, который возвращает целое число, создается сообщение на основе этого целого числа. Затем сообщение передается в UIAlterView и отображается для пользователя. Предупреждение не имеет никаких опций (поэтому я не вызываю делегата), а просто уведомляет пользователя о том, что произошло.

Редактировать Ниже приведен полный метод (ранее отображался частично). Когда я закомментирую все доUIAlertView и подставьте строку @ "test" вместо передачи сообщения, предупреждение отображается успешно. Я неправильно обрабатываю память своей структурой?

- (IBAction)joinButton {
    struct userInfo localUser;

    [emailAddress resignFirstResponder];

    //convert textField text to char array in structure
    localUser.firstName = [self convertStringtoCharArray:firstName.text];
    localUser.lastName = [self convertStringtoCharArray:lastName.text];
    localUser.username = [self convertStringtoCharArray:username.text];
    localUser.email = [self convertStringtoCharArray:emailAddress.text];
    localUser.ipAddress = [self convertStringtoCharArray:localIPAddress.text];
    localUser.latitude = currentLocation.coordinate.latitude;
    localUser.longitude = currentLocation.coordinate.longitude;

    //pass structure to be sent over socket
    int result = [myNetworkConnection registerWithServer:&localUser];

    NSString *message = nil;

    //process result of sending attempt
    if (result == 0) {
        //registration succesful
        message = [NSString stringWithString:@"Registration successful"];
    } else if (result == 1) {
        //server unavailable
        message = [NSString stringWithString:@"Server unavailable. Please check your wi-fi settings and try again."];
    } else if (result == 2) {
        //unable to establish connection
        message = [NSString stringWithString:@"Unable to communicate with server. Please check your wi-fi settings and try again."];
    } else if (result == 3) {
        //username already in use
        message = [NSString stringWithString:@"Username in use. Try another username."];
    }

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Registration"
                                                    message:message
                                                   delegate:nil 
                                          cancelButtonTitle:@"Ok" 
                                          otherButtonTitles:nil];

    [alert show];
    [alert release];
}

Когда я выполняю код, который iPhone выдает, как будто он собирается отобразить предупреждение, но вылетает. Я получаюEXC_BAD_ACCESS ошибка в консоли. Я правильно не выпускаю ни предупреждение, ни сообщение? Вот вывод консоли:

Program received signal:  “EXC_BAD_ACCESS”.
(gdb) backtrace
#0  0x30011944 in objc_msgSend ()
#1  0x3054803e in NSPopAutoreleasePool ()
#2  0x3054c808 in -[NSAutoreleasePool release] ()
#3  0x30936ac4 in _UIApplicationHandleEvent ()
#4  0x3204696c in PurpleEventCallback ()
#5  0x30254a76 in CFRunLoopRunSpecific ()
#6  0x3025416a in CFRunLoopRunInMode ()
#7  0x320452a4 in GSEventRunModal ()
#8  0x308f037c in -[UIApplication _run] ()
#9  0x308eea94 in UIApplicationMain ()
#10 0x000020bc in main (argc=1, argv=0x2ffff508) at /Users/reu2009/Documents/iPhone Development/Development/BuddyTracker/main.m:14
(gdb) frame 10
#10 0x000020bc in main (argc=1, argv=0x2ffff508) at /Users/reu2009/Documents/iPhone Development/Development/BuddyTracker/main.m:14 14       int retVal = UIApplicationMain(argc, argv, nil, nil);

Редактировать удален[message release]; и назначенные строки с помощью[NSString stringWithString]; на основе ответов.

Попытайтесь добавить точку останова в верхней части вашего метода. Затем используйте шаг в опцию, чтобы пройти через каждую строку. Вы сузили его до чего-то выше линии UIAlertView, но все еще слишком трудно понять, в чем проблема. В зависимости от того, на какой линии находится отладчик, когда появляется сообщение EXC-BAD-ACCESS, это будет ваша проблемная строка. Хорошее видео об основах отладки смотрите в блоге Джеффа Ламарша об отладке: Iphonedevelopment.blogspot.com / 2009/03 / debugging.html Ken Pespisa
No. та же ошибка. Я даже закомментировал блок создания условного сообщения. Eric de Araujo
Это происходит в самом конце метода. Кажется, вы правы, Кен, это что-то ранее в методе (см. Последнее редактирование). Eric de Araujo
работает, если вы заменяете message: message на message: @ "test"? Ken Pespisa
Очень странно. Вы пытались пройти через отладчик, чтобы выяснить, на какой линии происходит ошибка? Мне просто любопытно, ищем ли мы не в том месте. Ken Pespisa

Ваш Ответ

6   ответов
8

... вызывал его из основного потока

Это была моя проблема. Благодарность a1phanumeric
Для примера того, что означает j2emanue, смотрите / Stackoverflow.com вопросы / 12468677 / ... Ben Wheeler
4

возвращаемые конструкторами удобства, уже настроены на автоматический выпуск. Хотя вы объявили указатель на «message», сам объект «message» вам не принадлежит, поскольку вы использовали вспомогательный конструктор @ «string» для создания объекта NSString. Таким образом, вам не нужно выпускать его.

Когда вы отпускаете его вручную, он выходит слишком много раз (один раз вручную и один раз, когда происходит процесс автоматического выпуска) и выдает ошибку.

Вот дополнительная информация от Apple:

http: //developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.htm

Хорошее практическое правило: если вы не используете один из методов alloc, init или copy для создания объекта (или если вы сохраняете объект самостоятельно), вам не нужно его освобождать, но вы можете полагаться на метод, который фактически его создал чтобы сделать эту работу для вас.

Спасибо за это. Однако после удаления [выпуск сообщения]; Я получаю ту же ошибку. Это должно быть что-то за пределами освобождения строки сообщения. Eric de Araujo
Ну, тогда я сбит с толку. :) Я бы попробовал предложение Кена и, возможно, закомментировал строку «int result ...», чтобы увидеть, может ли какой-либо из них повлиять на проблему так или иначе. Sean McMains
Я считаю, что правило заключается в том, что методы, содержащие alloc, retain или copy, требуют, чтобы вы освободили объект. Mark
Ни замена строки сообщения, ни комментирование строки «int result» не приводят к отображению предупреждения. Может ли это быть что-то, что вызывается после «возврата» на клавиатуре? Я вызвал [текстовое поле resignFirstResponder]; но будет ли видимая клавиатура вызывать тревогу? Eric de Araujo
Добавлена заметка о сохранении объекта. Спасибо, Марк! Sean McMains
1

Войдите в информацию о вашем исполняемом файле. Нажмите на вкладку Аргументы. Нажмите + на «Переменные для установки в среде». Тип NSZombieEnable и ДА.

Когда освободится память, которая уже была освобождена, NSZombie отобразит адрес, затем вы можете использовать Инструменты, чтобы найти реальный объект. Домик Корбина имеет хороший обзор того, как это сделать: Инструменты на Leopard: как отладить эти случайные сбои в приложении Какао

0

потому что вы никогда не сохраняете объект сообщения.

Вместо того, чтобы просто сказатьmessage = @"string", тебе нужно сказатьmessage = [NSString stringWithString:@"string"]; Честно говоря, я не уверен, почему (возможно, кто-то может прокомментировать, и я могу улучшить этот пост!), Но это должно сработать.

Я уверен, что они делают то же самое ...@"string" а также[NSString stringWithString:@"string"] оба возвращают не сохраненные строки NSS. davidcann
0

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

ClassA

...

doSomething {
 ... some stuff ...

 [MyAlertView showAlert];

 ... some other stuff...

}

Что я подозреваю, так это то, что, когда я щелкаю по кнопке, объект оповещения отображается асинхронно.

Чтобы проверить это, я изменил код, чтобы создать экземпляр предупреждения, а не выпускать его. И все сработало.

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

0

Я решил это так

UIAlertView *alertMSG = [[UIAlertView alloc] initWithTitle:nil
                        message:@"Your mnessage here"
                        delegate:self
                        cancelButtonTitle:@"Title here"
                        otherButtonTitles: nil];

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
         [alertMSG show];
    }];

Похожие вопросы