I'm trying to make a music app that needs a very precise timer (it needs to be synced with background music). And I need to display the timer as a progress bar on the UI too.
I initially started with NSTimer
, turned out to be not accurate at all, with above 20ms off. And I turned to GCD. But I seem not to be able to get it work neither.
Here is my code (removed parts that are not related)
This is the first line in my ViewController class
var dispatchQueue = dispatch_queue_t()
And in my override func viewDidLoad()
function
dispatchQueue = dispatch_queue_create("myQueueId", nil)
Then the actual functions that use the dispatch queue
// Generate new measure
// In the main dispatch queue because it handles a lot of work
func newMeasure() {
timerBar.progress = 1.0
// Reset the timer
logEnd = NSDate()
let lapse = logEnd.timeIntervalSinceDate(logStart)
println("Lapse: \(lapse)")
logStart = NSDate()
// measureTimer is set to 1.47, so the newMeasure is supposedly to be called every 1.47 seconds
timer = measureTimer
startTime = NSDate()
dispatch_async(dispatchQueue, {
self.gameTimer()
})
// ... do a lot of stuff that will drag the timer if not put in dispatch queue
}
// Accurate Game Timer
// In the dispacheQueue so the timer can has its own thread
func gameTimer() {
// Get the time now
let now = NSDate()
let adjust = now.timeIntervalSinceDate(self.startTime)
// Refresh the start time to be now
self.startTime = now
self.timer = self.timer - adjust
// Go back to the main dispatch queue to update UI
dispatch_async(dispatch_get_main_queue(), {
self.timerBar.progress = Float(self.timer / self.measureTimer)
})
if (self.timer <= 0.2) {
dispatch_async(dispatch_get_main_queue(), {
// Going back to the main dispatch queue to start another new measure
NSTimer.scheduledTimerWithTimeInterval(self.timer, target: self, selector: Selector("newMeasure"), userInfo: nil, repeats: false)
})
}
else {
dispatch_after(dispatch_time_t(
100 * NSEC_PER_MSEC), dispatchQueue, {
self.gameTimer()
})
}
}
But the actual log looks like this:
Lapse: 1.47152501344681
Lapse: 1.51420003175735
Lapse: 1.47065001726151
Lapse: 1.47149801254272
Lapse: 1.471755027771
Lapse: 1.47201299667358
Lapse: 1.47167503833771
Lapse: 1.47148901224136
Lapse: 1.47146201133728
Lapse: 1.47289103269577
Lapse: 1.47580003738403
Lapse: 1.47087097167969
Lapse: 1.47286003828049
Lapse: 1.47235900163651
Lapse: 1.47159999608994
Lapse: 1.47144496440887
Lapse: 1.50616401433945
Lapse: 1.51679295301437
Lapse: 1.47380495071411
Lapse: 1.47130501270294
Lapse: 1.50468301773071
Lapse: 1.4718160033226
Lapse: 1.49480104446411
Lapse: 1.50195497274399
Lapse: 1.50018000602722
Lapse: 1.47339296340942
Lapse: 1.47266495227814
They still are not so on time. And because time is so sensitive to music, this is not gonna work. Can someone help me with this accuracy issue? Thank you