在我的iPad应用程序中,我试图使tableView以预定的时间间隔滚动。为此,我创建了一段代码,为每个滚动创建了一个闭合。但是,关闭比我想要的要晚几秒钟执行。这是一个简化的游乐场,它例证了相同的问题。

import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

// 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]
var times: [UInt64] = []

let dispatchStartTime = DispatchTime.now()

for index in 0 ..< lengths.count
{
    let delayNanoSeconds = Int(lengths[index] * 1_000_000_000)
    let dispatchLength = dispatchStartTime + .nanoseconds(delayNanoSeconds)
    times.append(dispatchLength.rawValue)

    DispatchQueue.main.asyncAfter(deadline: dispatchLength)
    {
        let delay = Double(DispatchTime.now().rawValue - times[index])
        print(delay/1_000_000_000)
    }
}


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

0.01646185
0.190259978
0.000302805
0.59319351
0.732933723
0.938841374
1.08249717
1.326286228
8.6309e-05
0.00019526
0.000104861
2.19584049
0.196220036
2.000116042
0.000425943
0.000202886


我可以容忍50-100毫秒的错误。但是,从结果中我们可以看到该错误可能大于2秒,并且它似乎随着关闭时间/关闭量的增加而增加。在我的应用程序中,此类间隔大约为100。是否有可能通过asyncAfter达到这种程度的特异性,还是一个更好的解决方案?

最佳答案

我已经实现了依赖于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()似乎不能在操场上工作,但是我的应用程序中的代码可以按预期工作,并且没有明显的延迟。

关于ios - DispatchTime.asyncafter的一致性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48358343/

10-09 02:44