Ios Swift中严格计划的循环定时
安排重复任务的最佳方式是什么?时间安排得非常严格(准确可靠,适合音乐排序)?从Apple文档中可以明显看出,NSTimer在这个意义上是不可靠的(即,“计时器不是实时机制”)。我从AudioKit公司借用的一种方法似乎在4ms内保持一致(如果不是很准确的话),并且可能是可行的:Ios Swift中严格计划的循环定时,ios,swift,nstimer,nsrunloop,Ios,Swift,Nstimer,Nsrunloop,安排重复任务的最佳方式是什么?时间安排得非常严格(准确可靠,适合音乐排序)?从Apple文档中可以明显看出,NSTimer在这个意义上是不可靠的(即,“计时器不是实时机制”)。我从AudioKit公司借用的一种方法似乎在4ms内保持一致(如果不是很准确的话),并且可能是可行的: class JHLoop: NSObject{ var trigger: Int { return Int(60 * duration) // 60fps * t in seconds
class JHLoop: NSObject{
var trigger: Int {
return Int(60 * duration) // 60fps * t in seconds
}
var counter: Int = 0
var duration: Double = 1.0 // in seconds, but actual loop is ~1.017s
var displayLink: CADisplayLink?
weak var delegate: JHLoopDelegate?
init(dur: Double) {
duration = dur
}
func stopLoop() {
displayLink?.invalidate()
}
func startLoop() {
counter = 0
displayLink = CADisplayLink(target: self, selector: "update")
displayLink?.frameInterval = 1
displayLink?.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)
}
func update() {
if counter < trigger {
counter++
} else {
counter = 0
// execute loop here
NSLog("loop executed")
delegate!.loopBody()
}
}
}
protocol JHLoopDelegate: class {
func loopBody()
}
类JHLoop:NSObject{
变量触发器:Int{
返回Int(60*持续时间)//60fps*t秒
}
变量计数器:Int=0
变量持续时间:Double=1.0//以秒为单位,但实际循环为~1.017s
var displayLink:CADisplayLink?
弱var委托:JHLoopDelegate?
初始(dur:Double){
持续时间=dur
}
func stopLoop(){
displayLink?.invalidate()
}
func startoop(){
计数器=0
displayLink=CADisplayLink(目标:self,选择器:“更新”)
displayLink?.frameInterval=1
displayLink?.addToRunLoop(NSRunLoop.currentRunLoop(),格式:NSRunLoopCommonModes)
}
func update(){
如果计数器<触发器{
柜台++
}否则{
计数器=0
//在这里执行循环
NSLog(“执行循环”)
委托!.loopBody()
}
}
}
协议委托:类{
func loopBody()
}
↑ 将代码替换为我将暂时尝试使用的实际类
作为参考,我希望制作一个多节奏的鼓音序器,所以一致性是最重要的。我还需要能够顺利修改循环,最好是实时修改循环周期
有更好的方法吗?您可以尝试使用mach\u wait\u until()api。这对于高精度定时器来说是非常好的。我把苹果的例子从一点点改过来。它在mine命令行工具项目中运行良好。在下面的代码片段中,我将
main()
方法从我的项目更改为startoop()
。你也可以看到。
希望能有帮助
static const uint64_t NANOS_PER_USEC = 1000ULL;
static const uint64_t NANOS_PER_MILLISEC = 1000ULL * NANOS_PER_USEC;
static const uint64_t NANOS_PER_SEC = 1000ULL * NANOS_PER_MILLISEC;
static mach_timebase_info_data_t timebase_info;
static uint64_t nanos_to_abs(uint64_t nanos) {
return nanos * timebase_info.denom / timebase_info.numer;
}
func startLoop() {
while(true) { //
int64_t nanosec = waitSomeTime(1000); // each second
NSLog(@"%lld", nanosec);
update() // call needed update here
}
}
uint64_t waitSomeTime(int64_t eachMillisec) {
uint64_t start;
uint64_t end;
uint64_t elapsed;
uint64_t elapsedNano;
if ( timebase_info.denom == 0 ) {
(void) mach_timebase_info(&timebase_info);
}
// Start the clock.
start = mach_absolute_time();
mach_wait_until(start + nanos_to_abs(eachMillisec * NANOS_PER_MILLISEC));
// Stop the clock.
end = mach_absolute_time();
// Calculate the duration.
elapsed = end - start;
elapsedNano = elapsed * timebase_info.numer / timebase_info.denom;
return elapsedNano;
}
这是非常有帮助的,包括代码,尤其是mach_Absolute_时间链接。