如何让两个不同的NS定时器同时工作?

时间:2015-12-18 03:32:52

标签: ios swift timer nstimer

我已经看到了另外一个这样的问题,但我没有帮助。在我的应用程序中,我想按下开始按钮时计时器开始计数。我还想从屏幕的一侧移动一个按钮到另一侧(当我点击开始按钮时)。为了增加这一点,我希望在点击开始按钮1秒后,另一个按钮从屏幕的一侧移动到另一侧。问题是,即使我为每个计时器(NS计时器)指定了一个不同的名称,它们也互相混淆。点击开始按钮后,用于计算秒数的计时器和移动工作的第一个按钮正常,但是在1秒后,第一个按钮返回到开头并重新开始,第二个按钮开始移动,但之后它也一样作为第一个按钮的东西。计算秒数的计时器仍然可以正常工作。下面是代码(BTW我使用CADisplayLink来移动按钮):

var displayLink: CADisplayLink?
var displayLink1: CADisplayLink?
@IBOutlet var moving1outlet: UIButton!
@IBOutlet var moving2outlet: UIButton!
@IBOutlet var timerlabel: UILabel!
var timer = NSTimer()
var timer2 = NSTimer()
var startTime = NSTimeInterval()
@IBAction func startbutton(sender: UIButton) {
     timer.invalidate()
    timer2.invalidate()
       //CREATING THE COUNTING TIMER
        let aSelector : Selector = "updateTime"
        timer2 = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: aSelector, userInfo: nil, repeats: true)
        startTime = NSDate.timeIntervalSinceReferenceDate()
    displayLink?.invalidate()
    displayLink1?.invalidate()
   //MOVING BUTTON 1
    moving1outlet.frame = CGRectMake(120, 400, 100, 100)
      displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
    displayLink?.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
   //DELAY TO MOVE BUTTON 2
     timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timerAction", userInfo: nil, repeats: false)  
}
func timerAction() {
    //MOVING BUTTON 2
    self.moving2outlet.frame = CGRectMake(120, 400, 100, 100)
    self.displayLink1 = CADisplayLink(target: self, selector: "handleDisplayLink1:")
    self.displayLink1?.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
}
func updateTime() {
    //COUNTING TIMER
    let currentTime = NSDate.timeIntervalSinceReferenceDate()
    //Find the difference between current time and start time.
    var elapsedTime: NSTimeInterval = currentTime - startTime
    //calculate the minutes in elapsed time.
    let minutes = UInt8(elapsedTime / 60.0)
    elapsedTime -= (NSTimeInterval(minutes) * 60)
    //calculate the seconds in elapsed time.
    let seconds = UInt8(elapsedTime)
    elapsedTime -= NSTimeInterval(seconds)
    //find out the fraction of milliseconds to be displayed.
    let fraction = UInt8(elapsedTime * 100)
    //add the leading zero for minutes, seconds and millseconds and store them as string constants
    let strMinutes = String(format: "%02d", minutes)
    let strSeconds = String(format: "%02d", seconds)
    let strFraction = String(format: "%02d", fraction)
    //concatenate minuets, seconds and milliseconds as assign it to the UILabel
    timerlabel.text = "\(strMinutes):\(strSeconds).\(strFraction)"
}
func handleDisplayLink(displayLink: CADisplayLink) {
    //POSITIONING BUTTON 1
    var buttonFrame = moving1outlet.frame
    buttonFrame.origin.y += -2
    moving1outlet.frame = buttonFrame
    if moving1outlet.frame.origin.y <= 50 {
        displayLink.invalidate()
        displayLink1?.invalidate()
    }
}
func handleDisplayLink1(displayLink1: CADisplayLink) {
    //POSITIONING BUTTON 2
    var button4Frame = moving2outlet.frame
    button4Frame.origin.y += -2
    moving2outlet.frame = button4Frame
    if moving2outlet.frame.origin.y <= 50 {
        displayLink1.invalidate()
    }
}

谢谢。安东

1 个答案:

答案 0 :(得分:0)

正如我在answer to your other question中的第1点提到的那样,您正在修改frame值,但毫无疑问您正在使用自动布局,因此触发自动布局引擎布局子视图的任何内容都会移动回到它们由约束定义的位置。所以问题不在于定时器,而是在改变frame值而不是改变约束。

一种解决方案是不更改frame值,而是创建约束的@IBOutlet引用,然后在显示链接处理程序中更改约束的constant而不是更改frame

例如,如果我想在2秒钟内使用显示链接将视点移动50点,我会做类似以下的事情。

首先,为主要约束添加一个出口:

enter image description here

然后我会像这样写一个显示链接处理程序:

@IBOutlet weak var leftConstraint: NSLayoutConstraint!

var displayLink: CADisplayLink?
var startTime: CFAbsoluteTime?
let duration = 2.0

override func viewDidLoad() {
    super.viewDidLoad()

    startDisplayLink()
}

func startDisplayLink() {
    startTime = CFAbsoluteTimeGetCurrent()
    displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
    displayLink?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}

func stopDisplayLink() {
    displayLink?.invalidate()
    displayLink = nil
}

func handleDisplayLink(displayLink: CADisplayLink) {
    let elapsed = CFAbsoluteTimeGetCurrent() - startTime!
    var percentComplete = CGFloat(elapsed / duration)

    if percentComplete >= 1.0 {
        percentComplete = 1.0
        stopDisplayLink()
    }

    leftConstraint.constant = 100.0 + 50.0 * percentComplete
}

请注意,就像我之前建议的那样,每次通话都不会移动固定的距离(因为不同的设备可能导致不同的速度,速度可能不会保持不变等等),而是我计算了&# 34;完成百分比&#34;根据经过的时间,然后从中计算坐标。