当视图控制器不是选定的选项卡或未显示时 NSTimer 停止
NSTimer stops when view controller is not the selected tab or not showing
我的倒数计时器有一个奇怪的问题。当我按下开始按钮时,它会正常启动,当我关闭应用程序并再次重新启动时,它会正确地重新实例化。然而,当我 select 一个不同的选项卡并在那里停留一段时间时,它停止倒计时,然后当我再次显示倒计时选项卡时从它停止的地方恢复倒计时。
例如,如果计时器现在位于 00:28:00
(格式为 HH:MM:SS),select 其他选项卡,停留 5 分钟,然后返回计时器选项卡,它仅在 27:52
标记处。当我关闭应用程序(双击主页按钮,向上滑动我的应用程序)并重新打开它时,它以更合理的 22:50
标记开始。
我已经发布了 class 中的相关代码来展示我是如何设置计时器的,但是它的作用的总结:
- 我在某处有加号 (+) 和减号 (-) 按钮,点击它们时会调用
recalculate()
。
recalculate()
触发 CalculateOperation
.
- A
CalculateOperation
根据新记录的 addition/removal 开始计算 HH:MM:ss。 CalculateOperation
的 successBlock
在主线程中执行。
- 如果尚未创建
countdownTimer
,则 CalculateOperation
在 successBlock
中创建 NSTimer
。
NSTimer
每1秒执行一次decayCalculation()
。它通过调用 tick()
. 将 calculation.timer
减少 1 秒
代码:
class CalculatorViewController: MQLoadableViewController {
let calculationQueue: NSOperationQueue // Initialized in init()
var calculation: Calculation?
var countdownTimer: NSTimer?
func recalculate() {
if let profile = AppState.sharedState.currentProfile {
// Cancel all calculation operations.
self.calculationQueue.cancelAllOperations()
let calculateOperation = self.createCalculateOperation(profile)
self.calculationQueue.addOperation(calculateOperation)
}
}
func decayCalculation() {
if let calculation = self.calculation {
// tick() subtracts 1 second from the timer and adjusts the
// hours and minutes accordingly. Returns true when the timer
// goes down to 00:00:00.
let timerFinished = calculation.timer.tick()
// Pass the calculation object to update the timer label
// and other things.
if let mainView = self.primaryView as? CalculatorView {
mainView.calculation = calculation
}
// Invalidate the timer when it hits 00:00:00.
if timerFinished == true {
if let countdownTimer = self.countdownTimer {
countdownTimer.invalidate()
}
}
}
}
func createCalculateOperation(profile: Profile) -> CalculateOperation {
let calculateOperation = CalculateOperation(profile: profile)
calculateOperation.successBlock = {[unowned self] result in
if let calculation = result as? Calculation {
self.calculation = calculation
/* Hide the loading screen, show the calculation results, etc. */
// Create the NSTimer.
if self.countdownTimer == nil {
self.countdownTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("decayCalculation"), userInfo: nil, repeats: true)
}
}
}
return calculateOperation
}
}
好吧,如果我将应用程序留在其他选项卡中并且有一段时间没有触摸 phone,它最终会进入休眠状态,应用程序退出活动状态,并进入后台,这会停止计时器。
解决方案是将我的视图控制器设置为 UIApplicationWillEnterForegroundNotification
的侦听器并调用 recalculate
来更正我的计时器的倒计时值。
我的倒数计时器有一个奇怪的问题。当我按下开始按钮时,它会正常启动,当我关闭应用程序并再次重新启动时,它会正确地重新实例化。然而,当我 select 一个不同的选项卡并在那里停留一段时间时,它停止倒计时,然后当我再次显示倒计时选项卡时从它停止的地方恢复倒计时。
例如,如果计时器现在位于 00:28:00
(格式为 HH:MM:SS),select 其他选项卡,停留 5 分钟,然后返回计时器选项卡,它仅在 27:52
标记处。当我关闭应用程序(双击主页按钮,向上滑动我的应用程序)并重新打开它时,它以更合理的 22:50
标记开始。
我已经发布了 class 中的相关代码来展示我是如何设置计时器的,但是它的作用的总结:
- 我在某处有加号 (+) 和减号 (-) 按钮,点击它们时会调用
recalculate()
。 recalculate()
触发CalculateOperation
.- A
CalculateOperation
根据新记录的 addition/removal 开始计算 HH:MM:ss。CalculateOperation
的successBlock
在主线程中执行。 - 如果尚未创建
countdownTimer
,则CalculateOperation
在successBlock
中创建NSTimer
。 NSTimer
每1秒执行一次decayCalculation()
。它通过调用tick()
. 将
calculation.timer
减少 1 秒
代码:
class CalculatorViewController: MQLoadableViewController {
let calculationQueue: NSOperationQueue // Initialized in init()
var calculation: Calculation?
var countdownTimer: NSTimer?
func recalculate() {
if let profile = AppState.sharedState.currentProfile {
// Cancel all calculation operations.
self.calculationQueue.cancelAllOperations()
let calculateOperation = self.createCalculateOperation(profile)
self.calculationQueue.addOperation(calculateOperation)
}
}
func decayCalculation() {
if let calculation = self.calculation {
// tick() subtracts 1 second from the timer and adjusts the
// hours and minutes accordingly. Returns true when the timer
// goes down to 00:00:00.
let timerFinished = calculation.timer.tick()
// Pass the calculation object to update the timer label
// and other things.
if let mainView = self.primaryView as? CalculatorView {
mainView.calculation = calculation
}
// Invalidate the timer when it hits 00:00:00.
if timerFinished == true {
if let countdownTimer = self.countdownTimer {
countdownTimer.invalidate()
}
}
}
}
func createCalculateOperation(profile: Profile) -> CalculateOperation {
let calculateOperation = CalculateOperation(profile: profile)
calculateOperation.successBlock = {[unowned self] result in
if let calculation = result as? Calculation {
self.calculation = calculation
/* Hide the loading screen, show the calculation results, etc. */
// Create the NSTimer.
if self.countdownTimer == nil {
self.countdownTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("decayCalculation"), userInfo: nil, repeats: true)
}
}
}
return calculateOperation
}
}
好吧,如果我将应用程序留在其他选项卡中并且有一段时间没有触摸 phone,它最终会进入休眠状态,应用程序退出活动状态,并进入后台,这会停止计时器。
解决方案是将我的视图控制器设置为 UIApplicationWillEnterForegroundNotification
的侦听器并调用 recalculate
来更正我的计时器的倒计时值。