Ios 如何使用NSUserDefaults保存NSTimer?敏捷的

Ios 如何使用NSUserDefaults保存NSTimer?敏捷的,ios,swift,nsdate,nstimer,nsdatecomponents,Ios,Swift,Nsdate,Nstimer,Nsdatecomponents,我想使用NSUserDefaults保存一个计时器以实现我的目标。不幸的是,当我尝试使用NSUserDefaults保存NSDate()时,它会变成静态的,并且不会继续计数。我做错什么了吗?同样,我的目标是让计时器仍然工作,不管它是进入后台还是被终止。它应该保存当前时间,并将其与剩余时间进行比较。这是到目前为止我的代码。解决此问题的其他代码在OBJ C中,并在后台使用,这是不必要的 func startTimer() { // then set time interval to expi

我想使用NSUserDefaults保存一个计时器以实现我的目标。不幸的是,当我尝试使用NSUserDefaults保存NSDate()时,它会变成静态的,并且不会继续计数。我做错什么了吗?同样,我的目标是让计时器仍然工作,不管它是进入后台还是被终止。它应该保存当前时间,并将其与剩余时间进行比较。这是到目前为止我的代码。解决此问题的其他代码在OBJ C中,并在后台使用,这是不必要的

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
}
func startTimer(){
//然后将时间间隔设置为expirationDate…
expirationDate=NSDate(timeintervalencenow:86400)
dateTimer=Timer.scheduledTimer(时间间隔:1.0,目标:self,选择器:#选择器(QOTDVC.updateUI(计时器:)),userInfo:nil,repeats:true)
RunLoop.current.add(dateTimer,forMode:RunLoopMode.commonModes)
NotificationCenter.default.post(名称:NSNotification.name(rawValue:“timeraded”),对象:nil)
}
func updateUI(计时器:计时器)
{
//调用currentTimeString方法,该方法可以减少时间。。
让timeString=currentTimeString()
timerLabel.text=“\(timeString)”
}
func currentTimeString()->DateComponents{
let unitFlags:Set=[.hour、.minute、.second]
让倒计时:DateComponents=Calendar.current.DateComponents(unitFlags,from:defaults.object(forKey:currentTime.description)作为!日期,to:expirationDate作为日期)
打印(“这是\(倒计时)”)
如果倒计时。秒!>0{
}否则{
dateTimer.invalidate()
}
返回倒计时
}

以下是我的完整代码示例。我希望这就是你想要的

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)"
}
}
导入UIKit
协议UserDefaultsTimerDelegate{
func timerAction(计时器:计时器,秒结束:Int)
}
类UserDefaultsTimer{
静态变量委托:UserDefaultsTimerDelegate?
类变量timerEndDate:日期{
得到{
将UserDefaults.standard.value(forKey:“timerEndDate”)返回为!Date?
}
设置(新值){
UserDefaults.standard.setValue(newValue,forKey:“timerEndDate”)
}
}
类变量timerInited:Bool{
得到{
如果let=timerEndDate{
返回真值
}否则{
返回错误
}
}
}
类func setTimer(日期:date,setdateonlyfcurrentimerisover:Bool){
如果!setDateOnlyIfCurrenTimerIsOver{
timerEndDate=日期
}否则{
如果!时间限制{
timerEndDate=日期
}否则{
让差异=timerEndDate!。秒(从:日期())
if(差分Int){
返回Calendar.current.dateComponents([.month],from:date,to:self)。月份??0
}
///返回从另一个日期算起的周数
func周数(从日期开始:日期)->Int{
返回Calendar.current.dateComponents([.weekOfYear],from:date,to:self)。weekOfYear??0
}
///返回从另一个日期算起的天数
func天(从日期开始:日期)->Int{
返回Calendar.current.dateComponents([.day],from:date,to:self).day±0
}
///返回从另一个日期算起的小时数
func小时数(从日期开始:日期)->Int{
返回Calendar.current.dateComponents([.hour],from:date,to:self).hour±0
}
///返回从另一个日期算起的分钟数
func分钟数(从日期开始:日期)->Int{
返回Calendar.current.dateComponents([.minute],from:date,to:self)。分钟??0
}
///返回从另一个日期算起的秒数
func秒(从日期开始:日期)->Int{
返回Calendar.current.dateComponents([.second],from:date,to:self).second±0
}
///返回从另一个日期开始的自定义时间间隔说明
func偏移量(从日期:日期)->字符串{
如果年(自:日期)>0{返回“\(年(自:日期))y”}
如果月份(从:日期起)>0{return“\(月份(从:日期起))M”}
如果周数(从:日期)>0{return“\(周数(从:日期))w”}
如果天(从:日期)>0{return“\(天(从:日期))d”}
如果小时数(从:日期)>0{返回“\(小时数(从:日期))h”}
如果分钟数(从:日期)>0{return“\(分钟数(从:日期))m”}
如果秒数(从:日期)>0{返回“\(秒数(从:日期))s”}
返回“”
}
}
类ViewController:UIViewController,UserDefaultsTimerDelegate{
var label=UILabel(帧:CGRect(x:40,y:40,宽度:60,高度:20))
重写func viewDidLoad(){
super.viewDidLoad()
//加载视图后,通常从nib执行任何其他设置。
label.text=“”
label.textColor=UIColor.black
view.addSubview(标签)
UserDefaultsTimer.delegate=self
UserDefaultsTimer.setTimer(日期:日期(timeIntervalSinceNow:50),setDateOnlyIfCurrenTimerIsOver:true)
UserDefaultsTimer.resumeTimer()
}
func timerAction(计时器:计时器,秒结束:Int){
label.text=“\(secondsToEnd)”
}
}

这是我的完整代码示例。我希望这是您想要的

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)"
}
}
导入UIKit
协议UserDefaultsTimerDelegate{
func timerAction(计时器:计时器,秒结束:Int)
}
类UserDefaultsTimer{
静态变量委托:UserDefaultsTimerDelegate?
类变量timerEndDate:日期{
得到{
将UserDefaults.standard.value(forKey:“timerEndDate”)返回为!Date?
}
设置(新值){
UserDefaults.standard.setValue(newValue,forKey:“timerEndDate”)
}
}
类变量timerInited:Bool{
得到{
如果let=timerEndDate{
返回真值
}否则{
返回错误
}
}
}
类func setTimer(日期:date,setdateonlyfcurrentimerisover:Bool){
如果!setDateOnlyIfCurrenTimerIsOver{
timerEndDate=日期
}否则{
如果!时间限制{
timerEndDate=日期
}否则{
让差异=timerEndDate!。秒(从:日期())
if(差分Int){
返回Calendar.current.dateComponents([.month],from:date,to:self)。月份??0
}
///返回从另一个日期算起的周数
func周数(从日期开始:日期)->Int{
返回Calendar.current.dateComponents([.we