如何在0.3秒后精确地执行一个动作达到给定的次数?
let expecation = expectationWithDescription("do tasks")
for i in 0...40 {
let afterTiming = 0.3 * Double(i)
let startTime = CFAbsoluteTimeGetCurrent()
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(afterTiming * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
print("(afterTiming) - (timeElapsed) : (i)")
}
}
waitForExpectationWithTimeout(14)
在30秒之后,控制台开始动作,同时显示两条和两条打印线
9.0 - 9.88806998729706 : 30
9.3 - 9.88832598924637 : 31
有没有办法让XCTest
更接近于“在正确的时间”实际执行请求? 就像在9.88秒之后没有完成9秒后应该完成的请求一样。
不知道你是否使用派遣,但NSTimer在我的测试中表现得更加准确。 以下是一些运行numOfTimes次操作的示例代码
var iterationNumber = 0
var startTime = CFAbsoluteTimeGetCurrent()
let numOfTimes = 30
// Start a repeating timer that calls 'action' every 0.3 seconds
var timer = NSTimer.scheduledTimerWithTimeInterval(0.3, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)
func action() {
// Print relevant information
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
print("(Double(iterationNumber+1) * 0.3) - (timeElapsed) : (CFAbsoluteTimeGetCurrent())")
// Increment iteration number and check if we've hit the limit
iterationNumber += 1
if iterationNumber > numOfTimes {
timer.invalidate()
}
}
该方案的一些输出:
7.8 - 7.80285203456879 : 25
8.1 - 8.10285001993179 : 26
8.4 - 8.40283703804016 : 27
8.7 - 8.70284104347229 : 28
9.0 - 9.00275802612305 : 29
9.3 - 9.3028250336647 : 30
它保持在预期时间的几毫秒内(我假设这是调用CFAbsoluteTimeGetCurrent所花费的时间),并且不会漂移或聚集在一起。
这种方法的一个缺点是它没有像在代码中那样预先安排每个动作,尽管我不确定这对你是否重要。
使用CADisplayLink
,一个高精度计时器
(不是一个很好的代码,只是快速入侵)
var displayLink: CADisplayLink?
var startTime: CFAbsoluteTime = 0
var nextTime: CFAbsoluteTime = 0
var index: Int = 0
func testIncrement() {
self.startTime = CFAbsoluteTimeGetCurrent()
self.nextTime = self.startTime
displayLink = CADisplayLink(target: self, selector: #selector(execute))
displayLink?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
let expectation = expectationWithDescription("test")
self.waitForExpectationsWithTimeout(20.0, handler: nil)
}
func execute() {
let currentTime = CFAbsoluteTimeGetCurrent()
if (currentTime - nextTime < 0) {
return
}
let timeElapsed = currentTime - startTime
print("(timeElapsed) : (index)")
index += 1
nextTime = startTime + 0.3 * CFAbsoluteTime(index)
if (index > 30) {
displayLink?.removeFromRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}
}
请注意,该方法实际上是多次执行的,并且在内部您必须检查是否有足够的时间流逝。
链接地址: http://www.djcxy.com/p/33515.html上一篇: How to perform an action exactly after 0.3 seconds for a given number of times?