2013-10-28 121 views
3

我正在转换旧的iPhone项目使用ARC。我提出了一个模态视图控制器,并在解雇它时获得EXC_BAD_ACCESS - 无法弄清楚原因,并且我怀疑我错过了ARC如何工作的基本原理。为什么使用ARC时此代码会导致EXC_BAD_ACCESS?

正在呈现的视图控制器是CorrectionsController,并且它使用委托来让它的呈现视图控制器知道关闭它。这些是从报头文件中的相关位:

@protocol CorrectionsControllerDelegate 
    - dismissCorrectionsController; 
@end 

@property (nonatomic, weak) id<CorrectionsControllerDelegate> correctionsDelegate; 

控制器被初始化在该方法中:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(id<CorrectionsControllerDelegate>)_delegate { 
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { 
     self.correctionsDelegate = _delegate; 
     // do other init stuff 
    } 
    return self; 
} 

的释放按钮调用此方法:

- (void)cancelCorrection { 
    if (self.correctionsDelegate) 
     [self.correctionsDelegate dismissCorrectionsController]; 
     // EXC_BAD_ACCESS happens here 
} 

呈递视图控制器像这样初始化CorrectionsController:

// in .h file 
@property (nonatomic, strong) CorrectionsController *corrections; 
@property (nonatomic, strong) UINavigationController *secondNavigationController; 

// in .m file 
    NSString *nibName = @"CorrectionsController"; 
    self.corrections = [[CorrectionsController alloc] initWithNibName:nibName bundle:nil delegate:self]; 
    self.secondNavigationController = [[UINavigationController alloc] initWithRootViewController:self.corrections]; 
    if (isiPad()) { 
     self.secondNavigationController.modalPresentationStyle = UIModalPresentationFormSheet; 
    } 
    [self presentViewController:self.secondNavigationController animated:YES completion:nil]; 

,它实现了CorrectionsControllerDelegate协议:

- (void)dismissCorrectionsController { 
    [self dismissViewControllerAnimated:TRUE completion:nil]; 
} 

现在,有趣的部分。在遍历代码时,执行流程将进入cancelCorrection,在代理中输入dismissCorrectionsController,返回cancelCorrection,并在取消修改的结束处返回EXC_BAD_ACCESS。

enter image description here

enter image description here

self.correctionsDelegate似乎指向在任何时候(检查它的变量视图的有效对象显示对象和值我希望,我也得到下面的控制台看起来没问题)。

(lldb) po self.correctionsDelegate 
<SyncController: 0x17b9a970> 

,真正让我困惑的部分:

1)堆栈跟踪显示EXC_BAD_ACCESS正在发生的事情里面objc_retain为什么?这里保留着什么?

2)0x44内存地址是指什么?

+0

请执行以下操作。在'cancelCorrection'方法的下一行if(self.correctionsDelegate)'中设置一个断点。当你的应用程序在控制台'po self.correctionsDelegate'中击中断点类型时,让我知道输出是什么。 – LuisCien

+0

更新了问题。据我可以告诉self.correctionsDelegate指向一个有效的对象,这是呈现视图控制器。 –

+0

由于这似乎是内存损坏错误('objc_retain'),您可能需要启用僵尸对象。另外,让我指出'if(someObject)[someObject someMethod];'是多余的,因为'[nil someMethod];'是有效的Objective-C – Olotiar

回答

0

最佳解释到目前为止,我发现模态控制器(CorrectionsController)似乎立即在dismissCorrectionsController中释放,并且在执行返回到cancelCorrection时不再有效。这一变化似乎解决崩溃:

- (void)cancelCorrection { 
    [self.correctionsDelegate performSelector:@selector(dismissCorrectionsController) ]; 
} 

所接受,但它仍然没有做出完整的意义,我,我会纪念这个答案,所以如果有人对正在发生的事情,我会很乐意更好的解释代之以接受该答案。

+0

尝试拆卸崩溃位置和/或单步执行汇编代码。 –

+0

有趣。你看过这个版本的堆栈跟踪吗?我们可以想象,'performSelector:'做了一些事情,比如调用performSelector:withObject:afterDelay:,立即返回并在运行循环中“排队”消息。 –

-1

我觉得这个回答非常晚,可以帮助提问者alex_c但它可以帮助某人。

代码有问题。

@protocol CorrectionsControllerDelegate 
    - dismissCorrectionsController; 
@end 

错过的返回类型。

@protocol CorrectionsControllerDelegate 
    - (void)dismissCorrectionsController; 
@end 
相关问题