4

When using a DateFormatter in the initialization of a struct like below, what's the cleanest way of caching that formatter?

struct Entry {
    let date: Date
    // ...

    init?(string: String) {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
        if let date = dateFormatter.date(from: string) {
            self.date = date
        } else {
            return nil
        }
        // ...
    }
}
Frederick Squid
  • 591
  • 4
  • 16

1 Answers1

8

Just assign it to a property:

struct Entry {
    let dateFormatter: DateFormatter
    // ...

    init?(string: String) {
        let df = DateFormatter()
        df.dateFormat = "yyyy-MM-dd hh:mm:ss"
        dateFormatter = df
        // ...
    }
}

However, because date formatters are somewhat expensive to create, it is very common to make these a static property so there is only one for the type rather than one for each instance.

struct Entry {
    private static let dateFormatter: DateFormatter = {
        let df = DateFormatter()
        df.dateFormat = "yyyy-MM-dd hh:mm:ss"
        return df
    }()
 }
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Ah, perfect. This feature to initialize a static property with a closure is what I forgot about. – Frederick Squid Jan 20 '18 at 17:16
  • 1
    Beware: prior to iOS 7 and macOS 10.9, `DateFormatter` is not threadsafe, so you can run into nasty bugs if you used a shared instance like this in a threaded context – Alexander Jan 20 '18 at 21:58
  • Another risk of this is race conditions. Let’s say you create two instances of Entry, the second one writes to the dateformatter, and then the first reads it but alas it is different from before... – ScottyBlades Jan 29 '21 at 23:28