简体   繁体   English

如何使用NSUserDefaults保存NSTimer? 迅速

[英]How to save NSTimer using NSUserDefaults? Swift

I want to save a timer using NSUserDefaults to accomplish my goal. 我想使用NSUserDefaults保存一个计时器来完成我的目标。 Unfortunately when I try to save the NSDate() using NSUserDefaults, it becomes static and won't continue counting. 不幸的是,当我尝试使用NSUserDefaults保存NSDate()时,它变成静态的,不会继续计数。 Am I doing something wrong? 难道我做错了什么? Again my goal is have the timer still work regardless of whether it went to background or got terminated. 我的目标再次是使计时器仍然工作,而不管它是进入后台还是被终止。 It should save the current time and compare it to how much time is remaining. 它应该保存当前时间,并将其与剩余时间进行比较。 Here is my code so far. 到目前为止,这是我的代码。 Other code addressing this issue is in OBJ C, and used didEnterBackground which is not necessary. 解决此问题的其他代码在OBJ C中,并使用了didEnterBackground(这是不必要的)。

func startTimer() {
    // then set time interval to expirationDate…

    expirationDate = NSDate(timeIntervalSinceNow: 86400 )
    dateTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(QOTDVC.updateUI(timer:)), userInfo: nil, repeats: true)
    RunLoop.current.add(dateTimer, forMode: RunLoopMode.commonModes)
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "TimerAdded"), object: nil)

}

func updateUI(timer: Timer)
{
    // Call the currentTimeString method which can decrease the time..
    let timeString = currentTimeString()
    timerLabel.text = "\(timeString)"
}
func currentTimeString() -> DateComponents  {
    let unitFlags: Set<Calendar.Component> = [.hour, .minute, .second]



    let countdown: DateComponents = Calendar.current.dateComponents(unitFlags, from: defaults.object(forKey: currentTime.description) as! Date, to: expirationDate as Date)


    print("this is the \(countdown)")

    if countdown.second! > 0 {

    } else {
        dateTimer.invalidate()


    }
        return countdown
}

Here is my full code example. 这是我的完整代码示例。 I hope this is what you wanted. 希望这就是您想要的。

import UIKit

protocol UserDefaultsTimerDelegate {
    func timerAction(timer: Timer, secondsToEnd:Int)
}

class UserDefaultsTimer {

static var delegate: UserDefaultsTimerDelegate?

class var timerEndDate: Date? {
    get {
        return UserDefaults.standard.value(forKey: "timerEndDate") as! Date?
    }
    set (newValue) {
        UserDefaults.standard.setValue(newValue, forKey: "timerEndDate")
    }
}

class var timerInited: Bool {
    get {
        if let _ = timerEndDate {
            return true
        } else {
            return false
        }
    }
}

class func setTimer(date: Date, setDateOnlyIfCurrenTimerIsOver: Bool) {
    if !setDateOnlyIfCurrenTimerIsOver {
        timerEndDate = date
    } else {
        if !timerInited {
            timerEndDate = date
        } else {
            let difference = timerEndDate!.seconds(from: Date())
            if (difference <= 0) {
                timerEndDate = date
            }
        }
    }
}

class func resetTimer() {
     timerEndDate = nil
}

class func resumeTimer() {
    if timerInited {
        NSLog("timer end date:\(timerEndDate)")
        let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(action(timer:)), userInfo: nil, repeats: true)
        RunLoop.current.add(timer, forMode: RunLoopMode.commonModes)
    }
}

@objc class func action(timer: Timer) {
    if let timerEndDate = timerEndDate {

        let difference = timerEndDate.seconds(from: timer.fireDate)
        if let delegate = delegate {
            delegate.timerAction(timer: timer, secondsToEnd: difference)
        }

        NSLog("timer: \(difference)")
        if (difference <= 0) {
            timer.invalidate()
            resetTimer()
        }
    } else {
        timer.invalidate()
        resetTimer()
    }
}
}

extension Date {
/// Returns the amount of years from another date
func years(from date: Date) -> Int {
    return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
}
/// Returns the amount of months from another date
func months(from date: Date) -> Int {
    return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
}
/// Returns the amount of weeks from another date
func weeks(from date: Date) -> Int {
    return Calendar.current.dateComponents([.weekOfYear], from: date, to: self).weekOfYear ?? 0
}
/// Returns the amount of days from another date
func days(from date: Date) -> Int {
    return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
}
/// Returns the amount of hours from another date
func hours(from date: Date) -> Int {
    return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
}
/// Returns the amount of minutes from another date
func minutes(from date: Date) -> Int {
    return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
}
/// Returns the amount of seconds from another date
func seconds(from date: Date) -> Int {
    return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
}
/// Returns the a custom time interval description from another date
func offset(from date: Date) -> String {
    if years(from: date)   > 0 { return "\(years(from: date))y"   }
    if months(from: date)  > 0 { return "\(months(from: date))M"  }
    if weeks(from: date)   > 0 { return "\(weeks(from: date))w"   }
    if days(from: date)    > 0 { return "\(days(from: date))d"    }
    if hours(from: date)   > 0 { return "\(hours(from: date))h"   }
    if minutes(from: date) > 0 { return "\(minutes(from: date))m" }
    if seconds(from: date) > 0 { return "\(seconds(from: date))s" }
    return ""
}
}

class ViewController: UIViewController, UserDefaultsTimerDelegate {

var label = UILabel(frame: CGRect(x: 40, y: 40, width: 60, height: 20))

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    label.text = ""
    label.textColor = UIColor.black
    view.addSubview(label)
    UserDefaultsTimer.delegate = self
    UserDefaultsTimer.setTimer(date: Date(timeIntervalSinceNow: 50), setDateOnlyIfCurrenTimerIsOver: true)
    UserDefaultsTimer.resumeTimer()
}

func timerAction(timer: Timer, secondsToEnd: Int) {
    label.text = "\(secondsToEnd)"
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM