2016-09-28 3 views
0

Ich möchte einen Timer mit NSUserDefaults speichern, um mein Ziel zu erreichen. Leider, wenn ich versuche, NSDate() mit NSUserDefaults zu speichern, wird es statisch und wird nicht weiter zählen. Mache ich etwas falsch? Wiederum ist es mein Ziel, dass der Timer immer noch funktioniert, egal ob er in den Hintergrund ging oder beendet wurde. Es sollte die aktuelle Zeit gespeichert und mit der verbleibenden Zeit verglichen werden. Hier ist mein Code soweit. Anderer Code, der dieses Problem anspricht, ist in OBJ C und verwendet didEnterBackground, was nicht notwendig ist.So speichern Sie NSTimer mit NSUserDefaults? Swift

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 
} 
+2

Sie können einen Timer nicht in 'NSUserDefaults' speichern. Siehe diese Frage: http://stackoverflow.com/questions/22628922/how-to-run-ntimer-in-background-beyond-180sec-in-ios-7 – random

+0

Ich las: http://StackOverflow.com/Questions/39753403/how-to-save-nstimer-using-nsuserdefaults-swift? Noredirect = 1 # comment66803063_39753403, und das scheint anders zu sagen. Ich verstehe nur nicht, warum es statisch bleibt. –

+1

Da Ihr Timer Sekunden zählt, warum verwenden Sie nicht die Systemzeit? Speichere die aktuelle Zeit und die verstrichenen Sekunden von deinem Zähler, wenn die App in den Hintergrund wechselt. – vadian

Antwort

1

Hier ist mein vollständiges Codebeispiel. Ich hoffe, das ist was du wolltest.

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

Also, haben Sie diese Lösung getestet? –

Verwandte Themen