当 Phone 进入飞行模式时计时器停止,离开 AM 后不会重新启动
Timer Stops When Phone Goes Into Airplane Mode, Won't Restart After Leaving AM
好的。查看了可能的答案,但我在这里没有看到我的问题。
我有一个相当标准的 GCD 重复计时器:
class RepeatingGCDTimer {
/// This holds our current run state.
private var state: _State = ._suspended
/// This is the time between fires, in seconds.
let timeInterval: TimeInterval
/// This is the callback event handler we registered.
var eventHandler: (() -> Void)?
/* ############################################################## */
/**
This calculated property will create a new timer that repeats.
It uses the current queue.
*/
private lazy var timer: DispatchSourceTimer = {
let t = DispatchSource.makeTimerSource() // We make a generic, default timer source. No frou-frou.
t.schedule(deadline: .now() + self.timeInterval, repeating: self.timeInterval) // We tell it to repeat at our interval.
t.setEventHandler(handler: { [unowned self] in // This is the callback.
self.eventHandler?() // This just calls the event handler we registered.
})
return t
}()
/// This is used to hold state flags for internal use.
private enum _State {
/// The timer is currently paused.
case _suspended
/// The timer has been resumed, and is firing.
case _resumed
}
/* ############################################################## */
/**
Default constructor
- parameter timeInterval: The time (in seconds) between fires.
*/
init(timeInterval inTimeInterval: TimeInterval) {
self.timeInterval = inTimeInterval
}
/* ############################################################## */
/**
If the timer is not currently running, we resume. If running, nothing happens.
*/
func resume() {
if self.state == ._resumed {
return
}
self.state = ._resumed
self.timer.resume()
}
/* ############################################################## */
/**
If the timer is currently running, we suspend. If not running, nothing happens.
*/
func suspend() {
if self.state == ._suspended {
return
}
self.state = ._suspended
self.timer.suspend()
}
/* ############################################################## */
/**
We have to carefully dismantle this, as we can end up with crashes if we don't clean up properly.
*/
deinit {
self.timer.setEventHandler {}
self.timer.cancel()
self.resume() // You need to call resume after canceling. I guess it lets the queue clean up.
self.eventHandler = nil
}
}
效果很好!
...除非没有。
那是我将设备设置为飞行模式的时间。
此时,计时器停止计时。
即使我退出飞行模式,计时器也不会重新启动。
该应用程序使用 UIApplication.shared.isIdleTimerDisabled = true/false 来保持应用程序处于唤醒状态,但这似乎并不能使事件继续发生。
谁能告诉我这里发生了什么,以及我如何解决它?
此应用需要在飞行模式下运行。其实最有可能在飞行模式下使用。
好的。我想我解决了这个问题。就像这些东西经常出现的情况一样,它是 PEBCAK。
我有一个例程可以在应用程序后台运行时停止计时器,而在应用程序前台运行时无法进行相应的重启。
当我向上滑动控制中心时,它使应用程序成为背景。
我的错。
是啊,这很尴尬,但我想把这个问题留在这里作为对其他人的警告。
好的。查看了可能的答案,但我在这里没有看到我的问题。
我有一个相当标准的 GCD 重复计时器:
class RepeatingGCDTimer {
/// This holds our current run state.
private var state: _State = ._suspended
/// This is the time between fires, in seconds.
let timeInterval: TimeInterval
/// This is the callback event handler we registered.
var eventHandler: (() -> Void)?
/* ############################################################## */
/**
This calculated property will create a new timer that repeats.
It uses the current queue.
*/
private lazy var timer: DispatchSourceTimer = {
let t = DispatchSource.makeTimerSource() // We make a generic, default timer source. No frou-frou.
t.schedule(deadline: .now() + self.timeInterval, repeating: self.timeInterval) // We tell it to repeat at our interval.
t.setEventHandler(handler: { [unowned self] in // This is the callback.
self.eventHandler?() // This just calls the event handler we registered.
})
return t
}()
/// This is used to hold state flags for internal use.
private enum _State {
/// The timer is currently paused.
case _suspended
/// The timer has been resumed, and is firing.
case _resumed
}
/* ############################################################## */
/**
Default constructor
- parameter timeInterval: The time (in seconds) between fires.
*/
init(timeInterval inTimeInterval: TimeInterval) {
self.timeInterval = inTimeInterval
}
/* ############################################################## */
/**
If the timer is not currently running, we resume. If running, nothing happens.
*/
func resume() {
if self.state == ._resumed {
return
}
self.state = ._resumed
self.timer.resume()
}
/* ############################################################## */
/**
If the timer is currently running, we suspend. If not running, nothing happens.
*/
func suspend() {
if self.state == ._suspended {
return
}
self.state = ._suspended
self.timer.suspend()
}
/* ############################################################## */
/**
We have to carefully dismantle this, as we can end up with crashes if we don't clean up properly.
*/
deinit {
self.timer.setEventHandler {}
self.timer.cancel()
self.resume() // You need to call resume after canceling. I guess it lets the queue clean up.
self.eventHandler = nil
}
}
效果很好!
...除非没有。
那是我将设备设置为飞行模式的时间。
此时,计时器停止计时。
即使我退出飞行模式,计时器也不会重新启动。
该应用程序使用 UIApplication.shared.isIdleTimerDisabled = true/false 来保持应用程序处于唤醒状态,但这似乎并不能使事件继续发生。
谁能告诉我这里发生了什么,以及我如何解决它?
此应用需要在飞行模式下运行。其实最有可能在飞行模式下使用。
好的。我想我解决了这个问题。就像这些东西经常出现的情况一样,它是 PEBCAK。
我有一个例程可以在应用程序后台运行时停止计时器,而在应用程序前台运行时无法进行相应的重启。
当我向上滑动控制中心时,它使应用程序成为背景。
我的错。
是啊,这很尴尬,但我想把这个问题留在这里作为对其他人的警告。