一些应用程序操作打破了TImer?

时间:2017-01-30 12:18:21

标签: ios swift multithreading timer nsuserdefaults

我有一个在我的应用程序上运行的计时器,它使用保存和重新加载功能,当用户离开视图并返回到视图时。但是,如果我转到我的应用程序上的其他选项卡,该选项卡所需的操作似乎打破了计时器。

这是因为应用程序中的线程使用情况以及另一个选项卡的coredata会导致计时器计数?这是我的计时器代码

更新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和控制台打印输出更改标签并再次更改时...

    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()
    }
}

enter image description here

1 个答案:

答案 0 :(得分:0)

尝试使用DateFormatter比较计时器(以毫秒为单位),并使用Notifications在控制器之间传递数据。

每次切换标签时都会调用此函数。它使计时器无效,停止计时,并以毫秒为单位节省时间。

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)
}

您需要定义将处理每个控制器中的通知的函数:

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")
    }
}

需要考虑的其他事项:您可能希望添加一些打印语句以进行调试/健全性检查,因为某些功能可能会先触发其他功能。例如,您可以尝试在viewWillDisappearviewDidDisappear中发布通知,而不是在prepare(for segue:)中发布通知。