1

我的主应用程序控制器调用一个子控制器来处理特定的屏幕序列。主控制器将自己设置为子控制器中的委托。当子控制器完成它的工作时,它会通知委托。有时,此通知会因 EXC_BAD_ACCESS 而失败。

0)基于gdb,问题出现在objc_msgSend。两个寄存器都有一个非零值。

gdb: 0x3367cc98  <+0016>  ldr   r5, [r4, #8]

1)我试过 NSZombiesEnabled 来跟踪问题,但当时我无法重现它。2)我尝试在有问题的命令之前设置断点,但我再次无法重现该问题。

我不知道发生了什么事。

这是委托属性声明(父控制器的寿命比子控制器长):

@property (assign) id<ParentControllerDelegate> delegate

这是有问题的代码:

- (void) doStuff {
   if(mode == Done) {
     NSLog(@"Done. Handling back control");//this is the last log displayed by the console
     [self.delegate done: self];
   } else {
     // some controller code
}

这是委托方的代码(委托已由 App_Delegate 保留,因为它是主控制器)。

- (void) done: (UIViewController *) caller {
   NSLog(@"Taken back control");// this never displays
   [caller.view removeFromSuperview];
   [caller release];
}

一些额外的信息:主控制器保留子控制器。我还修改了主控制器和子控制器中的 dealloc,以便在调用时进行记录。根据可见的日志,在应用程序过程中都不会调用。因此,消息的接收者和发送者都是有效对象。

我在这里真的很茫然。期待您的帮助。

4

3 回答 3

0

只是一个疯狂的猜测,但如果它是“偶尔”,它可能是viewDidLoadviewDidUnload导致EXC_BAD_ACCESS收到内存警告后。检查父/子控制器中释放/保留/创建的实例变量,尤其是在上述视图加载方法中。

于 2011-08-31T19:16:38.320 回答
0

如果从未执行过NSLog调用done:,那只能意味着您没有调用主控制器的done:. 这可能意味着这self.delegate是无效的。对象可能是有效的且活动的,但不是self.delegate它们之间的链接 ( )。请检查一下。在doStuff,在“完成”分支中,显示self.delegate地址

NSLog(@"%p", self.delegate);

在您致电done:并将其与主控制器的地址进行比较之前。

于 2011-08-31T19:22:42.693 回答
0

尝试在调用之前执行检查协议和方法,如代码中所示:

- (void) doStuff 
{
    if(mode == Done) 
    {
        NSLog(@"Done. Handling back control");//this is the last log displayed by the console
        if ([delegate conformsToProtocol: @protocol(ParentControllerDelegate)])
        {
            if ([delegate respondsToSelector: @selector(done:)] == YES)
            {
                [delegate performSelector: @selector(done:) withObject: self];            
            }
        }
    } 
    else 
    {
       // some controller code
于 2011-08-31T19:32:53.130 回答