【问题标题】:Object deallocated in ARC mode在 ARC 模式下释放对象
【发布时间】:2023-03-19 09:00:01
【问题描述】:

对象在 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

目前我无法估计任何线索,这让我老了。 任何意见将不胜感激!

【问题讨论】:

  • 什么是BlockAlertView?显示它的代码。
  • 这是我写的,比较长。不知道怎么给你看,即使它在那里,这可能是解除分配的原因吗?
  • 当然,创建和调用show 本身并不是保留alert 的理由...
  • 我们肯定需要查看 BlockAlertView。我也特别想看看委托的设置位置,因为如果它没有持续足够长的时间,就会非常可靠地导致这个错误。
  • 我将它声明为类属性 strong 并且崩溃已经消失,但我想保留我当前的代码。我在哪里可以发布代码?很长

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


【解决方案1】:

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

【讨论】:

  • 你的回答似乎很合理,我想将它声明为类的强属性,这不是解决这个问题的理想方法,但无论如何错误已经消失了
  • 当然,完成后记得将属性设置为nil,这样就可以清理对象了。
【解决方案2】:

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

这将要求您保留一个 strong ivar 以引用此“控制器”对象,并且在完成块中将 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;

【讨论】:

    【解决方案3】:

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

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

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

    id _selfReference;
    

    -show 中将self 分配给_selfReference

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

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

    【讨论】:

    • 没错,转ARC之前已经工作了
    猜你喜欢
    • 2012-10-01
    • 2013-06-24
    • 1970-01-01
    • 2012-05-04
    • 2013-11-29
    • 2012-01-30
    • 2015-07-24
    • 2013-09-07
    • 1970-01-01
    相关资源
    最近更新 更多