Я просматриваю образец кода Metronome из SDK iOS (http://developer.apple.com/library/ios/#samplecode/Metronome/Introduction/Intro.html). Я запускаю метроном при 60 BPM, что означает галочку каждую секунду. Когда я смотрю на внешние часы (часы ПК), я вижу, что метроном работает слишком медленно - он пропускает около одного бита каждую минуту, что является приложением. 15 мсек согласованной ошибки. Соответствующая часть кода:
- (void)startDriverTimer:(id)info {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Give the sound thread high priority to keep the timing steady.
[NSThread setThreadPriority:1.0];
BOOL continuePlaying = YES;
while (continuePlaying) { // Loop until cancelled.
// An autorelease pool to prevent the build-up of temporary objects.
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
[self playSound];
[self performSelectorOnMainThread:@selector(animateArmToOppositeExtreme) withObject:nil waitUntilDone:NO];
NSDate *curtainTime = [[NSDate alloc] initWithTimeIntervalSinceNow:self.duration];
NSDate *currentTime = [[NSDate alloc] init];
// Wake up periodically to see if we've been cancelled.
while (continuePlaying && ([currentTime compare:curtainTime] != NSOrderedDescending)) {
if ([soundPlayerThread isCancelled] == YES) {
continuePlaying = NO;
}
[NSThread sleepForTimeInterval:0.01];
[currentTime release];
currentTime = [[NSDate alloc] init];
}
[curtainTime release];
[currentTime release];
[loopPool drain];
}
[pool drain];
}
Где
self.duration
составляет 1,0 секунды в случае 60 BPM. Интересно, откуда эта ошибка, и как я могу сделать более точный счетчик таймера/интервала.
РЕДАКТИРОВАТЬ: Проблема также возникает, когда я изменяю время ожидания на меньшие значения, например .001.
EDIT2 (update): Проблема существует, когда я использую метод CFAbsoluteTimeGetCurrent()
для синхронизации. Когда я использую тот же метод для измерения времени между событиями нажатия кнопок, время кажется точным - я нажимаю один раз в секунду (при просмотре часов), а измеренная скорость составляет 60 BPM (в среднем). Поэтому я думаю, что это должна быть проблема с NSThread
(?). Другое дело, что на устройстве (iPod) проблема кажется более серьезной, чем на симуляторе.