我有一个在我的应用程序上运行的计时器,当用户离开 View 并返回 View 时,它使用保存和重新加载功能。但是,如果我在我的应用程序上转到不同的选项卡,该选项卡所需的操作似乎会破坏计时器。
这是否是由于应用程序中的线程使用和其他选项卡的核心数据打破了计时器计数?这是我的定时器代码
更新 2:这是我修改后的完整计时器代码......
// MARK: - SETTING UP SETS & TIMERS
func createStopTimeForRestFromUserTime(userTime: Int) -> Date {
let calendar = Calendar.current
let stopDate = calendar.date(byAdding: .second, value: userTime, to: Date())
return stopDate!
}
func createTimer(stopDate: Date) {
print("CONSTRUCTING A TIMER")
userDefaults.set(stopDate, forKey: "setStopDate")
restTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(RestController.updateRestTimer), userInfo: nil, repeats: true)
}
func updateRestTimer() {
let presentTime = Date()
let stoppedTime = UserDefaults.standard.object(forKey: "setStopDate") as? Date
if stoppedTime?.compare(presentTime) == ComparisonResult.orderedDescending {
restRemainingCountdownLabel.text = dateComponentsFormatter.string(from: presentTime, to: stoppedTime!)
} else {
self.stopTimer()
print("THE TIMER IS NOW FINISHED")
}
}
func stopTimer() {
self.restTimer.invalidate()
}
// MARK: - CONFIGURE TIMER ON OPEN / CLOSE
override func viewWillDisappear(_ animated: Bool) {
print("VIEWWILLDISAPPEAR WAS CALLED")
stopTimer()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ViewDidChangeNotification"), object: NSDate())
}
func handleResumedTime(disappTime: NSDate) {
let disappearedTime = disappTime
let resumeTime = NSDate()
if disappearedTime.compare(resumeTime as Date) == ComparisonResult.orderedDescending {
print("RESUMING THE TIMER")
self.createTimer(stopDate: disappearedTime as Date)
} else {
print("TIMER HAS FINISHED")
stopTimer()
}
}
func handleTimerCallback(notification: NSNotification) {
if let date = notification.object as? NSDate {
self.handleResumedTime(disappTime: date)
}
}
备用 VC id 开关中的代码导致损坏:
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(RoutineController.handleTimerCallback(notification:)), name: NSNotification.Name(rawValue: "ViewDidChangeNotification"), object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ViewDidChangeNotification"), object: NSDate())
}
func handleTimerCallback(notification: NSNotification) {
let date = notification.object
print("Object is \(date)")
}
编辑:添加了更新的 handleResumed 函数和控制台打印输出,当更改选项卡并再次更改回来时...
func handleResumedTime(disappTime: NSDate) {
let disappearedTime = disappTime as Date
let resumeTime = NSDate() as Date
print("ATTEMPTING RESUME")
print(disappearedTime)
print(resumeTime)
if resumeTime.compare(disappearedTime) == ComparisonResult.orderedAscending {
print("RESUMING THE TIMER")
self.createTimer(stopDate: disappearedTime)
} else {
print("TIMER HAS FINISHED")
stopTimer()
}
}
最佳答案
尝试使用 DateFormatter
以毫秒为单位比较计时器,并使用 Notifications
在 Controller 之间传递数据。
每次切换标签时都会调用此函数。它使计时器无效,停止滴答,并以毫秒为单位保存时间。
override func viewWillDisappear(_ animated: Bool) {
restTimer.invalidate()
let df = DateFormatter()
df.dateFormat = "y-MM-dd H:m:ss.SSSS"
let disappearingDate = Date()
let disappearingDateInMilliseconds = df.string(from: disappearingDate)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "kViewDidChangeExampleNotification"), object: disappearingDateInMilliseconds)
}
/* add your Notification observers in each view controller */
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.handleTimerCallback(notification:)), name: NSNotification.Name(rawValue: "kViewDidChangeExampleNotification"), object: nil)
}
您需要定义将处理每个 Controller 中的通知的函数:
func handleTimerCallback(notification: NSNotification) {
if let dateString = notification.object as? String {
print("Object is an String: \(notification.object)")
resumeTimerWithDate(dateString)
} else {
print("Object is not of type String: \(notification.object)")
}
}
以毫秒为单位比较 Swift 中的日期的快速示例:
func resumeTimerWithDate(dateString: String) {
let df = DateFormatter()
df.dateFormat = "y-MM-dd H:m:ss.SSSS"
let secondDate = Date()
let secondDateToStr = df.string(from: secondDate)
if dateString < secondDateToStr {
print("RESUMING THE TIMER")
let resumeDate = df.date(from: dateString)
self.createTimer(resumeDate)
} else {
print("TIMER HAS FINISHED")
}
}
其他需要考虑的事项:您可能想要添加一些打印语句以进行调试/完整性检查,因为某些函数可能先于其他函数触发。例如,与其在 viewWillDisappear
中发布通知,不如尝试在 viewDidDisappear
中发布通知,或使用 prepare(for segue:)
。
关于ios - 某些 App Actions 打破了 TImer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41935776/