【问题标题】:How to set delegate for case: Message sent to deallocated instance如何为案例设置委托:发送到已释放实例的消息
【发布时间】:2016-06-02 20:17:45
【问题描述】:

当我登录时,我通过 segue 从 VC1 调用 VC2

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if ([[segue identifier] isEqualToString: @"embeddedVC2"]) {
        self.VC2 = [segue destinationViewController];
        self.VC2.delegate = self;
    }
  }

我在 VC1 中有 dealloc

 -(void)dealloc{
   self.VC2.delegate=nil;
}

VC2 中的委托被声明为 (nonatomic,assign)

在 VC2 中,我正在执行下载操作,完成后我正在调用

  [self.delegate downloadFinish:self.downloadData];

问题是,当下载完成时,VC1 中的 dealloc 被调用,它使 VC2 中的委托为零。所以委托是零,并且 [self.delegate downloadFinish:self.downloadData];没用。

如果我在 VC1 dealloc 方法中删除了 self.VC2.delegate=nil,则会出现异常 在线:

   [self.delegate downloadFinish:self.downloadData];

发送到已释放实例的消息:因为 VC1 已释放,我无法对其执行任何操作。

处理这种情况的正确方法是什么?

注意:只有在我重新执行该过程时才会发生这种情况。

案例 1:登录 -> VC1 ->VC2 工作正常,委托通知我下载完成

案例2VC1中没有dealloc方法:

login -> VC1 -> VC2 -> logout ->login -> VC1 -> VC2 (boom) crash-messages sent to deallocated instance

案例 3在 VC1 中使用 dealloc,在其中使用 self.VC2.delegate=nil:

login -> VC1 -> VC2 -> logout ->login -> VC1 -> VC2 没有任何反应,因为 delegate 设置为 nil

我尝试使用僵尸仪器,但我有点不懂。我对长堆栈跟踪感到困惑,并且在查看引用计数和保留计数时迷失了方向。如果您需要,我可以将 stacktract 发布到仪器中。

编辑:

我将代理更改为nonatomicweak,并删除了dealloc 方法。

当我通过 segue 加载 VC2 时,viewDidLoad 中的 VC2 委托不是 nil,但在下载完成时它变成了 nil,此时我仍在 VC2 中.我想知道是什么让代理为零,因为我没有转到另一个 VC。

【问题讨论】:

  • 委托属性应该是weak,而不是assign
  • 如果我将其设置为弱,那么我还需要在 dealloc 方法中使委托为零吗?@rmaddy
  • 不,应该不需要设置dealloc。但如果你这样做,它不会受到伤害。
  • 它为我解决了一个困惑(案例 1&2),但代表是 nil 。我仍然对案例 3 有疑问。委托是零,即使我通过 segue 设置它。 @rmaddy
  • 你应该开始一个新问题,包括尽可能多的细节(如调用堆栈等)。 rmaddy已经回答了这个问题。

标签: ios objective-c delegates


【解决方案1】:

确保您要么推送 VC,呈现 VC,要么添加为 childViewController,这样父级不会被释放。否则,例如,如果您使用 tabbar,则需要确保 VC1 永远不会设置为 nil。

如果您花费太多时间尝试解决问题,我会重写您将 VC 添加到层次结构中的方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-21
    • 2011-06-16
    • 2023-03-13
    相关资源
    最近更新 更多