Ios Swift中严格计划的循环定时

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

安排重复任务的最佳方式是什么?时间安排得非常严格(准确可靠,适合音乐排序)?从Apple文档中可以明显看出,NSTimer在这个意义上是不可靠的(即,“计时器不是实时机制”)。我从AudioKit公司借用的一种方法似乎在4ms内保持一致(如果不是很准确的话),并且可能是可行的:

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_时间链接。