gpt4 book ai didi

ios - 为什么这个 dispatch_after 会立即触发?

转载 作者:行者123 更新时间:2023-11-28 07:02:55 26 4
gpt4 key购买 nike

这是我编写的用于将 NSTimeInterval 转换为基于 walltime 的 dispatch_time_t 的结构:

public struct WallTimeKeeper {

public static func walltimeFrom(spec: timespec)->dispatch_time_t {
var mutableSpec = spec
let wallTime = dispatch_walltime(&mutableSpec, 0)
return wallTime
}

public static func timeStructFrom(interval: NSTimeInterval)->timespec {
let nowWholeSecsFloor = floor(interval)
let nowNanosOnly = interval - nowWholeSecsFloor
let nowNanosFloor = floor(nowNanosOnly * Double(NSEC_PER_SEC))
println("walltimekeeper: DEBUG: nowNanosFloor: \(nowNanosFloor)")
var thisStruct = timespec(tv_sec: Int(nowWholeSecsFloor),
tv_nsec: Int(nowNanosFloor))
return thisStruct
}
}

我一直在尝试在 Playground 中测试它的准确性,但我的结果让我感到困惑。

这是我的 Playground 中的代码(我的 WallTimeKeeper 在 Sources 文件夹中):

var stop = false
var callbackInterval: NSTimeInterval?
var intendedTime: NSDate?
var intendedAction: ()->() = {}

func testDispatchingIn(thisManySeconds: NSTimeInterval){
intendedTime = NSDate(timeIntervalSinceNow: thisManySeconds)
intendedAction = stopAndGetDate
dispatchActionAtDate()
loopUntilAfterIntendedTime()
let success = trueIfActionFiredPunctually() //always returns false
}

func dispatchActionAtDate(){
let timeToAct = dateAsDispatch(intendedTime!)
let now = dateAsDispatch(NSDate())
/*****************
NOTE: if you run this code in a Playground, comparing the above two
values will show that WallTimeKeeper is returning times the
correct number of seconds apart.
******************/
dispatch_after(timeToAct, dispatch_get_main_queue(), intendedAction)
}

func loopUntilAfterIntendedTime() {
let afterIntendedTime = intendedTime!.dateByAddingTimeInterval(1)
while stop == false && intendedTime?.timeIntervalSinceNow > 0 {
NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode,
beforeDate: afterIntendedTime)
}
}

func trueIfActionFiredPunctually()->Bool{
let intendedInterval = intendedTime?.timeIntervalSinceReferenceDate
let difference = intendedInterval! - callbackInterval!
let trueIfHappenedWithinOneSecondOfIntendedTime = abs(difference) < 1
return trueIfHappenedWithinOneSecondOfIntendedTime
}

func dateAsDispatch(date: NSDate)->dispatch_time_t{
let intendedAsInterval = date.timeIntervalSinceReferenceDate
let intendedAsStruct = WallTimeKeeper.timeStructFrom(intendedAsInterval)
let intendedAsDispatch = WallTimeKeeper.walltimeFrom(intendedAsStruct)
return intendedAsDispatch
}

func stopAndGetDate() {
callbackInterval = NSDate().timeIntervalSinceReferenceDate
stop = true
}

testDispatchingIn(3)

...所以不仅 trueIfActionFiredPunctually() 总是返回 false,而且 difference 值——旨在测量回调触发时间与应该触发的时间——成功的结果应该非常接近 0,当然低于 1——结果与回调的时间量几乎完全相同应该等待开火。

总而言之:定义了等待的时间量,并设置了在该时间量后触发的操作。当 Action 触发时,它会创建触发时刻的时间戳。当将时间戳与其应有的值进行比较时,我们并没有接近零,而是接近了我们应该等待的时间。

换句话说,似乎传递给 dispatch_after 的操作立即触发,这绝对不应该!

这是 Playgrounds 有问题还是我的代码有问题?

编辑:这是代码。在实时应用程序中运行相同的代码会得到相同的结果。我做错了什么?

最佳答案

我想通了。这是一个令人头疼的问题。如果有人遇到同样的问题,我会保留它。

我正在使用 NSDate().timeIntervalSinceReferenceDate 来设置我的挂钟时间。

Walltimes 需要 NSDate().timeIntervalSince1970!

dispatch_after 任务全部立即触发,因为它们认为它们在四十多年前就已经安排好了!

将所有内容更改为 NSDate().timeIntervalSince1970 使其完美运行。

道德:除非您确定引用日期是 1970 年,否则不要使用挂钟时间!

关于ios - 为什么这个 dispatch_after 会立即触发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31629120/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com