Swift: can I add and subtract `dispatch_time_t` variables?
I need to do time math in iOS, with Swift.
I need to use dispatch_walltime
. I hope this can be considered axiomatic. Where is the math of the time, I think I'm most likely getting the answer "just use NSDate
", but please take it on faith: I have to dispatch_walltime
.
It is now clear why someone might suggest NSDate
, because when you use NSTimeInterval
and NSDate
, and this is good stuff, it's pretty easy to create your own timestamps, compare them, and do all kinds of time math.
But I have to use dispatch_time_t
, namely dispatch_walltime
, created like this:
//Get the timeInterval of now.
let nowInterval = NSDate().timeIntervalSince1970
//Make a timespec from it.
var nowStruct = timespec(tv_sec: Int(nowInterval), tv_nsec: 0)
//Make a walltime definition from that.
let referenceWalltime = dispatch_walltime(&nowStruct, 0)
Later I need to use this link time in various ways. For example, I need to get the time interval between the checkout time and the time it will happen.
I'm trying to do it the same way I do with NSTimeInterval
, in other words, make a new one and subtract the old one from it:
//Repeat everything from before to make a new wall time.
let newNowInterval = NSDate().timeIntervalSince1970
var newNowStruct = timespec(tv_sec: Int(newNowInterval), tv_nsec: 0)
let newWalltime = dispatch_walltime(& newNowStruct, 0)
//Time math a la NSTimeInterval to find the interval:
let walltimeInterval = newWalltime - referenceWalltime
Will this work?
source to share
The short answer is no. This code will work.
The best answer is no, but it can be done and it's not all that is different in the end.
I did some research on my own in the playground and learned some interesting things and I believe I figured out the right way to do it.
I am pasting my entire playground here so others can copy it and figure out how to do their own math dispatch_time
.
The comments marked with // ********* in the code denote key things that I've learned.
import UIKit
import XCPlayground
XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)
public class IntervalMaker {
var referenceWalltime: dispatch_time_t = 0
var newWalltime: dispatch_time_t = 0
var walltimeInterval: dispatch_time_t = 0
func scheduleWalltimeSequence () {
let threeSeconds = Int64(NSEC_PER_SEC) * 3
let now = walltimeNow()
let dispatchTimeInThree = dispatch_time(now, threeSeconds)
let dispatchTimeInSix = dispatch_time(now,
2 * threeSeconds)
setReferenceWalltimeToNow()
dispatch_after(dispatchTimeInThree, dispatch_get_main_queue(),
setNewWalltimeToNow)
dispatch_after(dispatchTimeInSix,
dispatch_get_main_queue(), dispatchBasedOnDispatchMath)
}
func walltimeNow()->dispatch_time_t{
let nowInterval = NSDate().timeIntervalSince1970
var nowStruct = timespec(tv_sec: Int(nowInterval), tv_nsec: 0)
return dispatch_walltime(&nowStruct, 0)
}
func setReferenceWalltimeToNow () {
referenceWalltime = walltimeNow()
}
func setNewWalltimeToNow (){
newWalltime = walltimeNow()
}
func dispatchBasedOnDispatchMath () {
computeInterval() //Should be three seconds
let nineTheWrongWay = referenceWalltime + (walltimeInterval * 3)
let nineTheRightWay = dispatch_time(referenceWalltime,
Int64(walltimeInterval) * 3)
dispatch_after(nineTheWrongWay,
dispatch_get_main_queue(), finalPrintln)
//********** THE ABOVE DOES NOT WORK CORRECTLY - prints 6 seconds later
dispatch_after(nineTheRightWay,
dispatch_get_main_queue(), finalPrintln)
//********** THE ABOVE WORKS CORRECTLY - prints 9 seconds later
}
func finalPrintln () {
let now = walltimeNow()
println("I should be printing nine seconds from reference time.")
println("It actually \(referenceWalltime - now) nanoseconds after")
}
func computeInterval () {
walltimeInterval = referenceWalltime - newWalltime
//********** dispatch_walltimes actually count backwards, and *CANNOT* be
//********** negative: writing `newWalltime - referenceWalltime` will crash
}
}
let intervaller = IntervalMaker()
intervaller.scheduleWalltimeSequence()
source to share