在 ARC 模式下释放对象

Object deallocated in ARC mode

对象在 ARC 模式下被释放并导致崩溃。我的代码如下;

BlockAlertView* alert = [BlockAlertView alertWithTitle:title message:message];
[alert setCancelButtonWithTitle:NSLocalizedString(@"No", @"No Button") block:nil];
[alert addButtonWithTitle:NSLocalizedString(@"Yes", @"Yes Button") block:^{
        //Do Something
}];
[alert show];

它出现了正确的警报视图(这是自定义 UIView),但是当我单击其中一个按钮时它崩溃了。

崩溃日志;

2015-04-07 22:28:17.065 Test[3213:781570] <BlockAlertView: 0x16bb4160> 2015-04-07 22:33:01.746 Test[3213:781570] *** -[BlockAlertView performSelector:withObject:withObject:]: message sent to deallocated instance 0x16bb4160

这里是BlockAlertView的源代码;

BlockAlertView on Github

现在我无法估计这方面的任何线索,让我老了。 任何输入将不胜感激!

将您的 alert 对象分配到您当前功能之外的某个地方。一种简单的可能性是将其设为实例变量。如果那不切实际,请创建一个您 allocate/init 的实例 NSMutableArray *retainedItems;,然后将其填充到其中。

看起来像是该项目中的设计缺陷。 class 命名不当 BlockAlertView 因为它实际上不是 UIView 的子 class。如果它是一个视图并且它被添加到视图层次结构中,那么视图层次结构将确保它在被查看时保持活动状态。因为它是视图保持活动状态,但是创建视图 BlockAlertView 的对象没有被任何东西保留,并且在调用操作时 BlockAlertView 早已不复存在。

这将要求您保留一个 strong ivar 来引用此 "controller" 对象,并且 nil 在完成块中删除该 ivar 是明智的。

BlockAlertView *alertController = [BlockAlertView alertWithTitle:title message:message]; {
  [alertController setCancelButtonWithTitle:NSLocalizedString(@"No", @"No Button") block:nil];

  __weak __typeof(self) weakSelf = self;
  [alertController addButtonWithTitle:NSLocalizedString(@"Yes", @"Yes Button") block:^{
    //Do Something
    weakSelf.alertController = nil;
  }];

  [alertController show];
}

self.alertController = alertController;

据推测,该代码在转换为 ARC 之前可以正常工作。

要修复它,您需要在 -show 方法中创建对 self 的强引用,并在 -dismissWithClickedButtonIndex:animated: 中释放此引用(您看到 [self autorelease] 注释掉了)。

您可以使用一个简单的实例变量来做到这一点:

id _selfReference;

-show中将self分配给_selfReference:

- (void)show
{
    _selfReference = self;
    ...

然后在 -dismissWithClickedButtonIndex:animated: 中看到 [self autorelease] 被注释掉的两个地方 _selfReference 设置为 nil