CATransaction 完成块永远不会触发

Posted

技术标签:

【中文标题】CATransaction 完成块永远不会触发【英文标题】:CATransaction completion block never fires 【发布时间】:2014-12-14 14:07:11 【问题描述】:

为什么这个 CATransaction 的完成块永远不会触发?

[CATransaction begin];
[CATransaction setCompletionBlock:^
    // table animation has finished
    NSLog(@"why does this section never execute?");
];
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.currentFeedItems.count inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
[CATransaction commit];

tableview 动画有效,但从不执行完成块。 Apple 文档说完成块保证会执行。

【问题讨论】:

你能告诉我们你在哪里/什么时候打电话,因为它在我这边工作。 它被调用以响应按钮按下 您能否详细说明您的问题? 我最初在表格单元格中设置了一个按钮,并使用委托来让控制器调用上述代码。没用。因此,考虑到它可能与它正在执行的线程有关,我将上面的代码包装在一个 dispatch_async(dispatch_get_main_queue()... 块中。没有工作。所以,我改为使用通知来触发上面的代码。没用。所以...最后我尝试将上面的代码放在控制器本身的一个简单方法中,当 didSelectRowAtIndexPath 触发时,调用此方法。这也不起作用。 【参考方案1】:

哦,天哪,这太晦涩难懂了,我真的很惊讶我发现了问题。

正在重新加载的单元格包含一个 UIActivityIndi​​catorView,它运行良好。当单元格重新加载时,它会隐式重绘表格单元格,并且在表格单元格的该进程中发生 startAnimating 调用。 startAnimating 调用以某种方式干扰了 CATransaction 完成块。

当我将 startAnimating 调用包装在 dispatch_async 块中时,问题就消失了:

dispatch_async(dispatch_get_main_queue(), ^
    [self.loadingInd startAnimating];
);

【讨论】:

感谢您提供解决方案。我有一个 CATransaction 块和一个一直在工作的完成块。在我最新的发布周期中的某个时刻,它只是......停止被调用。包装 dispatch_async 似乎已经修复了它。 (尽管在不理解 为什么 修复它的情况下这样做让我很痛苦!) 天哪,我不知道为什么会这样,但它也适用于我…… ***.com/a/37928557/1658268 进一步解释了为什么会发生这种情况 我的猜测是[CATransaction setCompletionBlock:] 将一些工作排​​入了负责设置完成的主队列中,因此通过将popViewControllerAnimated: 包装在异步调度中,我们正在等待该工作完成之前触发动画。这就是它起作用的原因。

以上是关于CATransaction 完成块永远不会触发的主要内容,如果未能解决你的问题,请参考以下文章

CATransaction 完成块成功或失败

iOS 在调用完成块之前会在 viewDidDisappear 之后等待 CATransaction

将动画添加到子视图时立即调用 CATransaction 完成块

TPL 数据流块永远不会在 PropagateCompletion 上完成

为啥在块外设置时,`scheduledTimer` 会正确触发,而不是在块内?

Swift/iOS - Firebase 远程配置获取值永远不会完成