【问题标题】:dispatch_after after dealloc issuedispatch_after 在 dealloc 问题之后
【发布时间】:2014-10-09 06:48:12
【问题描述】:

在 viewDidLoad 的 MyViewController 中,我只有一个调用:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.isNeedToExecute = YES;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self doSomeSimpleThings];
            });
}

-(void)doSomeSimpleThings {
      if (!self.isNeedToExecute) {
           return;
      }
      // do some simple actions
}

- (void)dealloc {
     self.isNeedToExecute = NO;
}

然后在代码中弹出这个视图控制器,所以如果没有dispatch_afterdealloc 肯定会被执行。

问题:

1) 这种情况下会调用dealloc方法吗(当我们有dispatch_after时,应该在20秒内执行)?

2) 这个方法[self doSomeSimpleThings];会在dealloc之后执行吗?

编辑:

我在发布这个问题之前尝试过,并且没有调用 dealloc 并认为它很奇怪,这就是我在这里问这个问题的原因。

【问题讨论】:

  • 您为什么不尝试一下并找出答案?你的问题真的是“如果我运行这段代码,会发生什么?”
  • 我会怀疑当您在dispatch_async() 块中引用self 时,该实例将被保留,因此将调用代码。你需要用不同的方法设置isNeedToExecute(比如viewDidDisappear)。
  • 1.在 dealloc 之后不会调用 doSomeSimpleThings。 2. 只有当你的 MyViewController 将从堆栈中删除时才会调用 dealloc。所以在你的情况下它不应该调用。
  • @borrrden,请看我的版本

标签: ios objective-c multithreading dealloc


【解决方案1】:

您当前的代码创建了一个保留循环,因为您在块内引用了self。您可以使用对self 的弱引用来打破循环。这样你也不需要isNeedToExecute 标志:

__weak id blockSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  [blockSelf doSomeSimpleThings];
});

在您的视图控制器 blockSelf 被释放后,nildoSomeSimpleThings 将不会被执行。

【讨论】:

  • 你能解释一下在retain cycle中哪个retain self吗?
  • @CarouselMin 这不是很明显吗?
  • 块保留内部引用的所有变量。但你是对的,在这种情况下它不是一个循环。引用会一直保留到计时器触发为止。
  • "您当前的代码创建了一个保留循环,因为您在块内引用了 self。"不。没有保留周期。
  • 在你的正上方查看我的评论。
【解决方案2】:

1) 在这种情况下会调用 dealloc 方法吗(当我们有 dispatch_after,应该在 20 秒内执行)?

dealloc 将在对象不再有强引用后被调用。该块持有对该对象的强引用。 dispatch_after 保留块直到它运行之后。所以 20 秒后,block 运行后,不会再有强引用,对象可以被释放(dealloc 调用)。

2) 将这个方法[self doSomeSimpleThings];后被执行 解除分配?

这是倒退。实际上,何时调用dealloc 取决于块(包含[self doSomeSimpleThings])何时运行。所以答案是否定的,根据定义,因为dealloc 无法运行,直到在这种情况下不再可能运行[self doSomeSimpleThings]

【讨论】:

    【解决方案3】:

    检查 dispatch_after 方法的定义。参数定义为

    queue:- 提交区块的队列。队列由系统保留,直到块运行完成。该参数不能为NULL。

    block: - <......>此函数代表调用者执行 Block_copy 和 Block_release。

    所以基本上你的控制器对象将被这个队列保留,即使你已经弹出它并且方法 doSomeSimpleThings 将被调用,然后 dealloc

    【讨论】:

    • 你的结论是正确的,但真正的原因是block保留了self
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 2011-02-20
    相关资源
    最近更新 更多