DispatchTime.asyncafter的一致性

时间:2018-01-20 16:20:03

标签: ios swift grand-central-dispatch dispatch-async

在我的iPad应用程序中,我试图让tableView以预定的间隔滚动。为此,我创建了一段代码,为每个滚动创建一个闭包。然而,关闭是在我想要的时间之后执行的。这是一个简化的Playground,它举例说明了同样的问题。

TempData

运行此项后,我收到了以下结果:(其他试验的结果类似,以及我的应用程序中运行的代码)

TempData

我可以容忍50-100毫秒的错误。但是从结果我们可以看出错误可能大于2秒,并且它似乎随着时间/闭包量而增长。在我的应用程序中,可以有大约100个这样的间隔。是否有可能通过asyncAfter达到这种特异性水平,或者一个替代方案,如忙碌等待的一个线程是否是更好的解决方案?

1 个答案:

答案 0 :(得分:0)

我已经实现了一个依赖于 mach_wait_until 的单线程版本。这对于准确性来说可能有点过分,但它似乎对能源使用没有任何强烈的负面影响。

import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

var timeInfo: mach_timebase_info = mach_timebase_info(numer: 0, denom: 0)
mach_timebase_info(&timeInfo)
// Intervals at which the delayed closures should run
var lengths: [Double] = [0.0, 2.0, 4.0,6.0,8.0,10.0,12.0,14.0,16.0, 18.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0, 32.0, 34.0, 36.0, 38.0, 40.0, 42.0, 44.0, 46.0, 48.0, 50.0, 52.0, 54.0, 56.0, 58.0, 60.0, 62.0, 64.0, 66.0, 68.0, 70.0]

let startTime = mach_absolute_time()

DispatchQueue.global().async()
{
    for index in 0 ..< lengths.count
    {
        let delayTicks = UInt64(lengths[index] * 1_000_000_000) * UInt64(timeInfo.denom) / UInt64(timeInfo.numer)
        mach_wait_until(startTime + delayTicks)

        DispatchQueue.main.async()
        {
            // UI changes
        }
    }
}

mach_until_wait()似乎不适用于游乐场,但我的应用中的代码按预期工作,并且没有任何明显的延迟。