使用ARC时,为什么此代码会导致EXC_BAD_ACCESS?

时间:2013-10-28 22:15:48

标签: ios iphone objective-c automatic-ref-counting

我正在转换旧的iPhone项目以使用ARC。我提出了一个模态视图控制器并在解除它时获取EXC_BAD_ACCESS - 无法弄清楚原因,我怀疑我遗漏了一些关于ARC如何工作的基本信息。

呈现的视图控制器是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;
}

dismiss按钮调用此方法:

- (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的 end 处返回cancelCorrection和EXC_BAD_ACCESS。

enter image description here

enter image description here

self.correctionsDelegate似乎始终指向一个有效的对象(在Variables视图中检查它会显示我期望的对象和值,并且我在控制台中看到以下内容中的以下内容)。

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

让我感到困惑的部分:

1)堆栈跟踪显示EXC_BAD_ACCESS正在 objc_retain 中发生。 为什么?这里保留了什么?

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

2 个答案:

答案 0 :(得分:0)

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

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

我会将这个答案标记为已被接受,但它对我来说仍然没有任何意义,所以如果有人对发生的事情有更好的解释,我会很乐意接受这个答案。

答案 1 :(得分:-1)

我认为这个答案很晚才能帮助提问者 alex_c ,但它可以帮助某人。

代码有问题。

@protocol CorrectionsControllerDelegate
   - dismissCorrectionsController;
@end

错过了返回类型。

@protocol CorrectionsControllerDelegate
   - (void)dismissCorrectionsController;
@end