Ios 时间太慢了

Ios 时间太慢了,ios,swift,time,nstimer,Ios,Swift,Time,Nstimer,我见过许多类似的问题;但是,没有一个解决了我的问题。我的计时器太慢了。我只使用了0.01秒的间隔。这是我的密码: @IBOutlet var timerLabel: UILabel! var miliseconds = 0 var seconds = 0 func updateLabel() { if miliseconds == 0 { timerLabel.text = "\(seconds).00" } else if miliseconds <

我见过许多类似的问题;但是,没有一个解决了我的问题。我的计时器太慢了。我只使用了
0.01
秒的间隔。这是我的密码:

@IBOutlet var timerLabel: UILabel!

var miliseconds = 0
var seconds = 0

func updateLabel() {
    if miliseconds == 0 {
        timerLabel.text = "\(seconds).00"
    } else if miliseconds < 10 {
        timerLabel.text = "\(seconds).0\(miliseconds)"
    } else {
        timerLabel.text = "\(seconds).\(miliseconds)"
    }
}

var timer = NSTimer()

func updateTime() {

    miliseconds++
    if miliseconds == 100 {
        miliseconds = 0
        seconds++
    }
    updateLabel()
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if timerState == 1 {
        timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "updateTime", userInfo: nil, repeats: true)
        NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
        timerLabel.textColor = UIColor.blackColor()
        timerState = 2
    }
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if timerState == 0 {
        miliseconds = 0
        seconds = 0
        updateLabel()
        timerLabel.textColor = UIColor.greenColor()
        timerState = 1
    } else if timerState == 2 {
        timerState = 0
        timer.invalidate()
    }
}

var timerState = 0
//timerState of 0 = Has not started
//timerState of 1 = About to start
//timerState of 2 = Timing
我在
viewDidLoad
中调用了
updateTime
,在
updateTime
的末尾,我添加了:

delay(0.01) { () -> () in
    self.updateTime()
}
然而,它仍然以与以前相同的速度前进


如何解决此问题?如果我在研究过程中遗漏了一个问题,请告诉我。谢谢

这里有一大堆问题。让我们清理一下

class ViewController: UIViewController {

    @IBOutlet var timerLabel: UILabel!
首先,不要使用计时器来更新标签。使用
CADisplayLink
。显示链接与屏幕刷新间隔同步,在大多数iOS设备上,屏幕刷新间隔为1/60秒(不是1/100),因此您不需要做额外的工作:

    private var displayLink: CADisplayLink?
接下来,不要试图在计时器(或链接)启动时通过增加计数器来跟踪经过的时间,因为计时器或链接不能保证按您要求的频率启动。相反,存储计时器启动的时间和停止的时间(如果已停止):

使用
enum
而不是神秘的硬编码数字跟踪状态。由于标签颜色仅取决于状态,请向状态添加一个属性,为该状态提供标签颜色:

    private enum State {
        case Stopped
        case Pending
        case Running

        var labelColor: UIColor {
            switch self {
            case .Pending: return UIColor.greenColor()
            case .Stopped, .Running: return UIColor.blackColor()
            }
        }
    }
运行时间取决于状态,因此添加一个方法来计算它:

    private var elapsedTime: NSTimeInterval {
        switch state {
        case .Stopped: return endTime - startTime
        case .Running: return CFAbsoluteTimeGetCurrent() - startTime
        case .Pending: return 0
        }
    }
更新标签时,使用格式字符串将经过的时间转换为字符串:

    private func updateLabel() {
        timerLabel.text = String(format: "%.02f", elapsedTime)
    }
更改计时器状态可以同时更改标签颜色和经过的时间,因此在状态更改时更新标签颜色和标签文本:

    private var state = State.Stopped {
        didSet {
            timerLabel.textColor = state.labelColor
            updateLabel()
        }
    }
触摸开始时,如果需要,创建显示链接,然后更新状态。州的
didSet
将根据需要处理标签更新:

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        createDisplayLinkIfNeeded()

        switch state {
        case .Stopped:
            state = .Pending
        case .Pending:
            break
        case .Running:
            state = .Stopped
            endTime = CFAbsoluteTimeGetCurrent()
            displayLink?.paused = true
        }
    }
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if state == .Pending {
            startTime = CFAbsoluteTimeGetCurrent()
            displayLink?.paused = false
            state = .Running
        }
    }
下面是显示链接将调用的方法:

    func displayLinkDidFire(_: CADisplayLink) {
        updateLabel()
    }

} // end of ViewController
从我上面的评论来看。。。(鼓励)


NSTimer-来自apple开发者文档:

“计时器不是一种实时机制;只有当其中一个 已添加计时器的运行循环模式正在运行且可启用 检查计时器的触发时间是否已过。由于 输入源一个典型的运行循环管理,有效解决 计时器的时间间隔限制在50-100之间 毫秒。”


你能解释一下你要解决的问题吗?0.01秒是否足以完成你在每个周期中要求的任务?否则,将延迟/跳过执行间隔。而且,
NSTimer
的分辨率较低。读一读《尤利西斯》,我的计时器太慢了。我如何修复它?NSTimer-来自apple开发者文档:“计时器不是一种实时机制;仅当添加了计时器的运行循环模式之一正在运行并且能够检查计时器的触发时间是否已过时,它才会触发。由于典型运行循环管理的各种输入源,计时器的时间间隔的有效分辨率限制在50-100毫秒左右。“@penatheboss定时器太慢了,这不是你的问题,你是在计算按钮按下的时间吗?我看了答案…似乎它能解决我的问题。我会在有机会的时候试试。谢谢你的回答!好的。所以我试了代码,几乎所有的东西都很好。但是,当我停止定时器时,我得到了一个信号。”e负数作为我的结束时间…这可能是什么原因?我在设置
endTime
后忘记更新标签。我在
endTime
中添加了一个
didSet
观察者来解决问题。因此建议可能使用时间戳
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if state == .Pending {
            startTime = CFAbsoluteTimeGetCurrent()
            displayLink?.paused = false
            state = .Running
        }
    }
    private func createDisplayLinkIfNeeded() {
        guard self.displayLink == nil else { return }
        let displayLink = CADisplayLink(target: self, selector: "displayLinkDidFire:")
        displayLink.paused = true
        displayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
        self.displayLink = displayLink
    }
    func displayLinkDidFire(_: CADisplayLink) {
        updateLabel()
    }

} // end of ViewController