@AppStorage with Date in SwiftUI

Hello

I want to be able to save Date in @AppStorage, and it works however I was wondering what was the difference between these two extensions, which one is better and why?

extension Date: RawRepresentable {
    static var dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .long
        return formatter
    }()
    
    public var rawValue: String {
        Date.dateFormatter.string(from: self)
    }
    
    public init?(rawValue: String) {
        self = Date.dateFormatter.date(from: rawValue) ?? Date()
    }
}

and

extension Date: RawRepresentable {
    private static let formatter = ISO8601DateFormatter()
    
    public var rawValue: String {
        Date.formatter.string(from: self)
    }
    
    public init?(rawValue: String) {
        self = Date.formatter.date(from: rawValue) ?? Date()
    }
}

Thank You!

Accepted Reply

Is there a better way to save Date in @AppStorage

One possible solution:

extension Date: RawRepresentable {
    public var rawValue: Double {
        self.timeIntervalSinceReferenceDate
    }
    
    public init?(rawValue: Double) {
        self = Date(timeIntervalSinceReferenceDate: rawValue)
    }
}

(UPDATE)

I want to be able to initialize it like this @AppStorage("date") var date = Date()

Sorry, I was missing that Int or String is needed for automatic conversion.

Please try this:

extension Date: RawRepresentable {
    public var rawValue: String {
        self.timeIntervalSinceReferenceDate.description
    }
    
    public init?(rawValue: String) {
        self = Date(timeIntervalSinceReferenceDate: Double(rawValue) ?? 0.0)
    }
}
  • But in this case @AppStorage("date") var date = Date().rawValue, date isn't a Date, it's a Double So if I try to bound it in a DatePicker it won't work

  • I want to be able to initialize it like this @AppStorage("date") var date = Date()

Add a Comment

Replies

Your #1 is locale-dependent. When user change the Language settings of the device, the saved date would not be able to be retrieved. Also, it lacks time information.

Your #2 lacks sub-second information. Re-read value may not be exactly the same as was when saved.

  • Thank you. Is there a better way to save Date in @AppStorage?

Add a Comment

Is there a better way to save Date in @AppStorage

One possible solution:

extension Date: RawRepresentable {
    public var rawValue: Double {
        self.timeIntervalSinceReferenceDate
    }
    
    public init?(rawValue: Double) {
        self = Date(timeIntervalSinceReferenceDate: rawValue)
    }
}

(UPDATE)

I want to be able to initialize it like this @AppStorage("date") var date = Date()

Sorry, I was missing that Int or String is needed for automatic conversion.

Please try this:

extension Date: RawRepresentable {
    public var rawValue: String {
        self.timeIntervalSinceReferenceDate.description
    }
    
    public init?(rawValue: String) {
        self = Date(timeIntervalSinceReferenceDate: Double(rawValue) ?? 0.0)
    }
}
  • But in this case @AppStorage("date") var date = Date().rawValue, date isn't a Date, it's a Double So if I try to bound it in a DatePicker it won't work

  • I want to be able to initialize it like this @AppStorage("date") var date = Date()

Add a Comment
extension Date: RawRepresentable {
    public var rawValue: String {
        self.timeIntervalSinceReferenceDate.description
    }
    
    public init?(rawValue: String) {
        self = Date(timeIntervalSinceReferenceDate: Double(rawValue) ?? 0.0)
    }
}

This one works Thank you!

Worked for me...thanks!

I used a setter and a getter. I got the idea from Nick Roosevelt on this post on forums.swift.org. (Thanks Nick!)

I realise it's not an extension on Date, but it's quick & simple and easy to understand, and it's working well for me.

@AppStorage("storedStartTime") var storedStartTime = Date.now.timeIntervalSinceReferenceDate
var startTime: Date {
    set {storedStartTime = newValue.timeIntervalSinceReferenceDate}
    get {return Date(timeIntervalSinceReferenceDate: storedStartTime)}
}