当应用程序进入后台时如何暂停 Timer()
How to pause Timer() when the app goes into the background
所以我被卡住了,我正在构建一个宾果应用程序,我希望该应用程序在进入后台时停止计时器。我的代码看起来像这样
var timer = Timer()
func ViewDidLoad(){
// other stuff
timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(numberPicker), userInfo: nil, repeats: true)
}
在我读到的其他帖子中,我看到有人建议将计时器定义为弱变量。当我尝试这个时,我的应用程序在尝试设置计时器时崩溃了。
试试这个。当应用程序从后台 returns 时,计时器也会重新启动。
class ViewController: UIViewController {
var timer = Timer()
var timerPaused = false
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default
.addObserver(self,
selector: #selector(applicationDidEnterBackground),
name: UIApplication.didEnterBackgroundNotification,
object: nil)
NotificationCenter.default
.addObserver(self,
selector: #selector(applicationDidBecomeActive),
name: UIApplication.didBecomeActiveNotification,
object: nil)
timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(numberPicker),
userInfo: nil,
repeats: true)
}
@objc
func applicationDidEnterBackground(_ notification: Notification) {
if !timerPaused {
timer.invalidate()
timerPaused = true
}
}
@objc
func applicationDidBecomeActive(_ notification: Notification) {
if timerPaused {
timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(numberPicker),
userInfo: nil,
repeats: true)
timerPaused = false
}
}
@objc
func numberPicker(_ sender: Any) {
}
}
Swift 5:
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.willResignActiveNotification, object: nil)
}
@objc func appMovedToBackground() {
timer.invalidate()
}
现代解决方案是 DispatchSourceTimer
可以暂停和恢复。
两个通知观察者也使用现代 swifty 基于块 API,不需要 @objc
。
let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
override func viewDidLoad() {
super.viewDidLoad()
timer.schedule(deadline: .now() + .seconds(5), repeating: 5.0)
timer.setEventHandler {
print("Timer fired")
}
NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main) { [weak self] _ in
self?.timer.suspend()
}
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { [weak self] _ in
self?.timer.resume()
}
timer.activate()
}
所以我被卡住了,我正在构建一个宾果应用程序,我希望该应用程序在进入后台时停止计时器。我的代码看起来像这样
var timer = Timer()
func ViewDidLoad(){
// other stuff
timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(numberPicker), userInfo: nil, repeats: true)
}
在我读到的其他帖子中,我看到有人建议将计时器定义为弱变量。当我尝试这个时,我的应用程序在尝试设置计时器时崩溃了。
试试这个。当应用程序从后台 returns 时,计时器也会重新启动。
class ViewController: UIViewController {
var timer = Timer()
var timerPaused = false
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default
.addObserver(self,
selector: #selector(applicationDidEnterBackground),
name: UIApplication.didEnterBackgroundNotification,
object: nil)
NotificationCenter.default
.addObserver(self,
selector: #selector(applicationDidBecomeActive),
name: UIApplication.didBecomeActiveNotification,
object: nil)
timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(numberPicker),
userInfo: nil,
repeats: true)
}
@objc
func applicationDidEnterBackground(_ notification: Notification) {
if !timerPaused {
timer.invalidate()
timerPaused = true
}
}
@objc
func applicationDidBecomeActive(_ notification: Notification) {
if timerPaused {
timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(numberPicker),
userInfo: nil,
repeats: true)
timerPaused = false
}
}
@objc
func numberPicker(_ sender: Any) {
}
}
Swift 5:
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.willResignActiveNotification, object: nil)
}
@objc func appMovedToBackground() {
timer.invalidate()
}
现代解决方案是 DispatchSourceTimer
可以暂停和恢复。
两个通知观察者也使用现代 swifty 基于块 API,不需要 @objc
。
let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
override func viewDidLoad() {
super.viewDidLoad()
timer.schedule(deadline: .now() + .seconds(5), repeating: 5.0)
timer.setEventHandler {
print("Timer fired")
}
NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main) { [weak self] _ in
self?.timer.suspend()
}
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { [weak self] _ in
self?.timer.resume()
}
timer.activate()
}