gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-10-31 23:44:21 28 4
gpt4 key购买 nike

我已经看到另外 1 个类似的问题,但我没有帮助。在我的应用程序中,我希望计时器在我按下开始按钮时开始计时。我还想将一个按钮从屏幕的一侧移动到另一侧(当我单击开始按钮时)。除此之外,我希望另一个按钮在单击开始按钮延迟 1 秒后从屏幕的一侧移动到另一侧。问题是,即使我为每个计时器 (NS Timer) 指定了不同的名称,它们也会相互混淆。单击开始按钮后,用于计算秒数的计时器和移动的第一个按钮工作正常,但 1 秒后,第一个按钮回到开头并重新开始,第二个按钮开始移动但然后它做同样的事情作为第一个按钮的东西。计算秒数的计时器仍然可以正常工作。这是代码(顺便说一句,我使用 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()
}
}

谢谢。安东

最佳答案

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

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

例如,如果我想在 2 秒内使用显示链接将 View 移动 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
}

请注意,就像我之前建议的那样,我不会在每次调用时移动固定距离(因为不同的设备可能会导致不同的速度,速度可能不会恒定等),而是计算“完成百分比”根据耗时,然后从中计算坐标。

关于ios - 如何让两个不同的 NS 定时器同时工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34348139/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com