UIView.animate 似乎冻结了其他视图更新
UIView.animate seems to freeze other view updates
我有一个 UIView,它是一个倒计时时钟,我用 UIView.animate 制作动画。还有一个 运行 计时器,当计时器被触发时,它会在 UILabel 上显示时间。当游戏处于转换状态时(倒计时期间),UILabel 停止更改。我已将 "print" 语句放入计时器函数中,它按预期显示。
我一直在寻找有关 UIVIew.animate 可能会冻结其他视图的提示,但我看到多个应用程序同时移动视图。也许我应该把东西放在不同的线程上?
@objc func timerUpdate () {
if gameIsRunning {
let endTime = Date.init()
let difference = endTime.timeIntervalSince(gameClock)
let formattedString = String(format: "%3.1f",kDefaultGameClock - difference)
timerLabel.text = "\(formattedString)"
}
}
private func countDownFrom (x: Int) {
if x != 0 && x > 0 {
UIView.animate(withDuration: 1.0,
delay: 0.0,
usingSpringWithDamping: 0.5,
initialSpringVelocity:1.0,
options: .curveEaseOut,
animations: {
self.successLabel.text = "\(x)"
self.successLabel.transform = self.successLabel.transform.scaledBy(x: 4.0, y: 4.0)
}, completion: {_ in
self.successLabel.transform = self.successLabel.transform.scaledBy(x: 0.250, y: 0.250)
if (x - 1 > 0) {
self.countDownFrom(x: x - 1)
} else {
self.successLabel.text = kDefaultGoodGame
self.successLabel.isHidden = true
self.startTheGame()
self.updateScreen()
}
})
}
}
当我在空项目中尝试您的代码时,我能够更新两个标签。
如果 timerLabel
没有更新,可能是线程问题。 UI更新应该在主线程上。
DispatchQueue.main.async {
self.timerLabel.text = "\(formattedString)"
}
对于它的价值,这是我在一个空项目中的工作。
@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var successLabel: UILabel!
let kDefaultGameClock = 30.0
var gameIsRunning = false
var gameClock = Date()
override func viewDidLoad() {
super.viewDidLoad()
start()
}
func start() {
gameIsRunning = true
countDownFrom(x: 30)
Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(timerUpdate), userInfo: nil, repeats: true)
}
@objc func timerUpdate() {
if gameIsRunning {
let endTime = Date.init()
let difference = endTime.timeIntervalSince(gameClock)
let formattedString = String(format: "%3.1f", kDefaultGameClock - difference)
timerLabel.text = "\(formattedString)" // Could be a main thread issue here?
}
}
private func countDownFrom(x: Int) {
if x != 0 && x > 0 {
UIView.animate(withDuration: 1.0,
delay: 0.0,
usingSpringWithDamping: 0.5,
initialSpringVelocity:1.0,
options: .curveEaseOut,
animations: {
self.successLabel.text = "\(x)"
self.successLabel.transform = self.successLabel.transform.scaledBy(x: 4.0, y: 4.0)
}, completion: {_ in
self.successLabel.transform = self.successLabel.transform.scaledBy(x: 0.250, y: 0.250)
if (x - 1 > 0) {
self.countDownFrom(x: x - 1)
} else {
self.successLabel.text = ""
self.successLabel.isHidden = true
//self.startTheGame()
//self.updateScreen()
}
})
}
}
有点偏离主题,但您可能希望将 Timer 声明为一个变量,以便在完成更新 timerLabel 后使其失效。
我有一个 UIView,它是一个倒计时时钟,我用 UIView.animate 制作动画。还有一个 运行 计时器,当计时器被触发时,它会在 UILabel 上显示时间。当游戏处于转换状态时(倒计时期间),UILabel 停止更改。我已将 "print" 语句放入计时器函数中,它按预期显示。
我一直在寻找有关 UIVIew.animate 可能会冻结其他视图的提示,但我看到多个应用程序同时移动视图。也许我应该把东西放在不同的线程上?
@objc func timerUpdate () {
if gameIsRunning {
let endTime = Date.init()
let difference = endTime.timeIntervalSince(gameClock)
let formattedString = String(format: "%3.1f",kDefaultGameClock - difference)
timerLabel.text = "\(formattedString)"
}
}
private func countDownFrom (x: Int) {
if x != 0 && x > 0 {
UIView.animate(withDuration: 1.0,
delay: 0.0,
usingSpringWithDamping: 0.5,
initialSpringVelocity:1.0,
options: .curveEaseOut,
animations: {
self.successLabel.text = "\(x)"
self.successLabel.transform = self.successLabel.transform.scaledBy(x: 4.0, y: 4.0)
}, completion: {_ in
self.successLabel.transform = self.successLabel.transform.scaledBy(x: 0.250, y: 0.250)
if (x - 1 > 0) {
self.countDownFrom(x: x - 1)
} else {
self.successLabel.text = kDefaultGoodGame
self.successLabel.isHidden = true
self.startTheGame()
self.updateScreen()
}
})
}
}
当我在空项目中尝试您的代码时,我能够更新两个标签。
如果 timerLabel
没有更新,可能是线程问题。 UI更新应该在主线程上。
DispatchQueue.main.async {
self.timerLabel.text = "\(formattedString)"
}
对于它的价值,这是我在一个空项目中的工作。
@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var successLabel: UILabel!
let kDefaultGameClock = 30.0
var gameIsRunning = false
var gameClock = Date()
override func viewDidLoad() {
super.viewDidLoad()
start()
}
func start() {
gameIsRunning = true
countDownFrom(x: 30)
Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(timerUpdate), userInfo: nil, repeats: true)
}
@objc func timerUpdate() {
if gameIsRunning {
let endTime = Date.init()
let difference = endTime.timeIntervalSince(gameClock)
let formattedString = String(format: "%3.1f", kDefaultGameClock - difference)
timerLabel.text = "\(formattedString)" // Could be a main thread issue here?
}
}
private func countDownFrom(x: Int) {
if x != 0 && x > 0 {
UIView.animate(withDuration: 1.0,
delay: 0.0,
usingSpringWithDamping: 0.5,
initialSpringVelocity:1.0,
options: .curveEaseOut,
animations: {
self.successLabel.text = "\(x)"
self.successLabel.transform = self.successLabel.transform.scaledBy(x: 4.0, y: 4.0)
}, completion: {_ in
self.successLabel.transform = self.successLabel.transform.scaledBy(x: 0.250, y: 0.250)
if (x - 1 > 0) {
self.countDownFrom(x: x - 1)
} else {
self.successLabel.text = ""
self.successLabel.isHidden = true
//self.startTheGame()
//self.updateScreen()
}
})
}
}
有点偏离主题,但您可能希望将 Timer 声明为一个变量,以便在完成更新 timerLabel 后使其失效。