【问题标题】:Swift UIAnimation blocked by for loopSwift UIAnimation 被 for 循环阻塞
【发布时间】:2020-10-11 05:24:39
【问题描述】:

我有一个提取消息日志的 UIAnimation,但我还需要使用 for 循环填充消息日志。我在 for 循环开始之前发生了动画,但是,直到 for 循环完成执行后,动画才真正开始(即使循环位于 UIAnimation 之后)。

我尝试将 for 循环的内容放在自动释放池中(没有用)

我曾尝试在后台线程上运行 for 循环,但是,循环中的大部分代码都需要在主线程上执行,而这种方法我没有成功。

for循环很大,大部分代码与问题无关,所以你可以用任何UIAnimation来设置,任何相对耗时的for循环...

例如:

let someView = UIView(frame:CGRect(x:self.view.frame.size.width,y:0,width:self.view.frame.size.width,height:self.view.frame.size.height))
someView.backgroundColor = .red
UIView.animate(withDuration:0.3,animations:{
    self.someView.frame.origin.x = 0
})

//You can wrap this with something like:
//DispatchQueue.global(qos: .background).async(execute: {
//But this^ doesn't work on the majority of the code within the loop
for i in 0...1000{
    print("hopefully this loop takes a few seconds to finish executing")
    print("mainthread tasks being executed")
    print("populating UITable in my particular case, and rendering Images/Video/text")
}

我可以让它变得更好的最接近的方法是在我的 UIAnimation 中添加一个“完成”(这将允许 UIView 完全/立即退出)但是在第一个之前还有一秒钟的等待时间消息出现...

另外,我在 for 循环中填充了一个 UITableView。不确定这是否与我遇到的主要问题有任何额外的相关性......

我非常熟悉 DispatchQueue 以及异步/同步之间的区别。如果您有任何潜在的解决方案或想法,请告诉我。

【问题讨论】:

标签: swift asynchronous async-await dispatch


【解决方案1】:

当您调用UIView.animate 时,动画不会立即发生。相反,所有动画都被收集并在某个适当的时间运行。这就是为什么动画仅在您的 for 循环完成后开始的原因。

所以修复它的方法是让动画在您的for 循环运行之前运行。现在,接受你所说的,for 必须在主线程上运行,你有很多选择。您可以将for 循环放在DispatchQueue.main.async{} 中,或者以某种方式将其调低,以便动画首先开始。您使用完成的想法是一个很好的想法,但您提到了一些您从中发现的实际问题。因此,要么解决这些实际问题,尝试在 DispatchQueue.main.async{} 内运行 for ,甚至基于实际考虑,在主线程上启动 for 循环,但在其他地方,比如 didLayoutSubviews (固定) 或者像现在一样与动画一起但经过几毫秒的延迟以允许动画开始。

【讨论】:

  • DispatchQueue.main.async{} 不起作用,我将不得不尝试做更好的预加载之类的......我没听说过 didLayoutComponents,我可以'在谷歌上找不到...你的意思是 didLayoutSubviews 吗?
  • 嗨 - 是的,对不起,我即兴写了。我认为最好的选择是在完成块中做一些事情。它会迫使你认真思考它,并且在其他方​​面你希望最好。无论如何,我很惊讶 Dispatch ... 没有工作。我认为如果您在暂停后发送它,它应该可以工作。动画被安排在主队列上,你希望循环安排在这之后,我认为完成是最好的。但是暂停也应该这样做,并且在适当的条件下可能会做 didLayoutSubviews。
  • 这里的主要内容是动画被安排 - 它们不会立即执行。并且您想安排您的 for 也在主循环上执行,但在动画开始之后。这可能非常棘手 - 我正在寻找一些在动画开始或结束时发送但没有找到的通知。我没有深入研究它,但是动画之后可能会发送一些消息,例如 didLayoutSubviews,然后 bob 是你的叔叔!但我再次认为最好是通过完成块以某种方式做到这一点。
【解决方案2】:

这是一个有趣的问题。这让我思考!

是的,您提到您了解异步/同步之间的区别,但没有提及您是否尝试在主线程中制作动画。

你试过把 UIView.animate(...)DispatchQueue.main.async{}?

【讨论】:

  • 是的,整个函数都是从主线程执行的,所以它对我没有任何影响。为了确定,我确实进行了测试。
  • 好的。您是否为for 循环尝试过这些案例? .userInitiated, .userInteractive
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
相关资源
最近更新 更多