UIAlertView 无法显示并导致“EXC_BAD_ACCESS”; 错误

发布于 2024-07-26 20:19:34 字数 3251 浏览 2 评论 0原文

当按下键盘上的返回按钮时,将调用一个方法。 调用另一个返回整数的方法后,将根据该整数创建一条消息。 然后该消息被传递到 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];分配了字符串。

A method is called when a return button on the keyboard is pressed. After calling another method which returns an integer a message is created based on that integer. The message is then passed into an UIAlterView and displayed to the user. The alert doesn't have any options (hence why I'm not calling a delegate), but simply notifies the user of what happened.

Edit: Below is the full method (previously displayed partial). When I comment out everything before the UIAlertView and substitute the string @"test" instead of passing message the Alert is shown successfully. Am I not handling memory correctly with my structure?

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

When I execute the code the iPhone greys out like it is about to display an alert but crashes. I get a EXC_BAD_ACCESS error in the console. Am I not releasing either the alert or the message correctly? Here is the console output:

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);

Edit: removed [message release]; and assigned strings using [NSString stringWithString]; based on answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

dawn曙光 2024-08-02 20:19:34

我遇到了这样的问题...我从后台线程调用 uiAlertView ....从主线程调用它

i had an issue like this ...i was calling uiAlertView from a background thread ....call it from the main thread

骷髅 2024-08-02 20:19:34

从便利构造函数返回的对象已设置为自动释放。 当您声明了一个指向“message”的指针时,“message”对象本身并不属于您,因为您使用了 @“string” 便捷构造函数来创建 NSString 对象。 因此,您不需要释放它。

当您手动释放它时,它会被释放太多次(一次手动释放,一次在自动释放过程滚动时释放)并引发错误。

以下是 Apple 提供的一些附加信息:

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

好的经验法则:除非您使用 alloc 或 init 或 copy 方法之一来创建对象(或者如果您自己保留该对象)您不需要释放它,但可以依靠实际创建它的方法来为您完成这项工作。

Objects returned from convenience constructors are already set to autorelease. While you declared a pointer to "message", the "message" object itself doesn't belong to you, since you used the @"string" convenience constructor to create the NSString object. Thus, you don't need to release it.

When you release it manually, it then gets released too many times (once manually, and once when the autorelease process rolls around) and throws the error.

Here's some additional information from Apple:

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

Good rule of thumb: unless you use one of the alloc or init or copy methods to create an object (or if you retain the object yourself) you don't need to release it, but can rely on the method that actually created it to do that work for you.

神妖 2024-08-02 20:19:34

尝试使用 NSZombieEnabled = YES。

  • 进入可执行文件的信息。
  • 单击“参数”选项卡。
  • 单击“要在环境中设置的变量”上的 +。
  • 键入 NSZombieEnable 和 YES。

当已经释放的内存被释放时,NSZombie会显示地址,然后你可以使用Instruments找到实际的对象。 Corbin 的树屋很好地概述了如何做到这一点:
Leopard 上的工具:如何调试 Cocoa 应用程序中的随机崩溃

Try it with NSZombieEnabled = YES.

  • Go into the Info of you Executable.
  • Click on the Arguments tab.
  • Click + on "Variables to be set in the environment."
  • Type NSZombieEnable and YES.

When the memory is released that has already been released, NSZombie will display the address, then you can use Instruments to find the actual object. Corbin's Treehouse has a good overview of how to do this:
Instruments on Leopard: How to debug those random crashes in your Cocoa app

思念绕指尖 2024-08-02 20:19:34

Sean 是对的 - 您不需要在这里调用 [消息释放],因为您实际上从未保留消息对象。

你需要说 message = [NSString stringWithString:@"string"]; 而不是仅仅说 message = @"string" ,说实话,我不确定为什么(也许有人可以发表评论,我可以改进这篇文章!)但这应该可以解决问题。

Sean is right - you don't need to call [message release] here, because you're never actually retaining the message object.

Instead of just saying message = @"string", you need to say message = [NSString stringWithString:@"string"]; To be completely honest I'm not sure why (maybe someone can comment and I can improve this post!) but that should do the trick.

红焚 2024-08-02 20:19:34

我在这里使用 UIAlertView 遇到了同样的问题,就我而言,我有另一个类实现警报,并且从另一个类中我调用了静态方法。 如下所示:

ClassA

...

doSomething {
 ... some stuff ...

 [MyAlertView showAlert];

 ... some other stuff...

}

我怀疑的是,当我单击按钮时,警报视图异步显示,因此对象已经被释放。

为了验证这一点,我更改了代码以实例化警报而不是释放它。 一切都奏效了。

我的最终解决方案是在父视图中声明一个变量,并在视图释放时将其与其他变量一起释放。

I had the same problem here with a UIAlertView, in my case, I had another class implementing the alert, and, from another one I was calling a static method. Like the following:

ClassA

...

doSomething {
 ... some stuff ...

 [MyAlertView showAlert];

 ... some other stuff...

}

What I suspect is that, as the alertview is shown asynchronously when I clicked the button the object was already released.

To verify that, I changed the code to instantiate the alert and not release it. And everythong worked.

My final solution was to declare a variable in the parent view, and deallocate it with the other variables when the view is deallocated.

∝单色的世界 2024-08-02 20:19:34

这可能是由于从后台线程更新 UIKit 导致的,

我这样解决了它

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

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

This could case due to updating UIKit from background thread

I solved it like this

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

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
         [alertMSG show];
    }];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文