Skip to main content

How to Cache NSDateFormatter?

Instantiating NSDateFormatter objects is slow. Most well-written apps that use NSDateFormatter will make efforts to reduce the number unique instances created. Using a static property is sufficient for most cases, but what if you work on a large app where lots of NSDateFormatter objects are needed by a large number of classes. Wouldn’t it be nice if there was an NSCachedDateFormatter that keeps track of what it has instantiated and will return cached objects and only instantiate new ones when necessary? Wouldn’t it be nice if NSCachedDateFormatter was a singleton and could be used app-wide? Here's a sample class that can be used to fulfill this need.

class CachedDateFormatter {
    static let sharedInstance = CachedDateFormatter()
    var cachedDateFormatters = [String: NSDateFormatter]()

    func formatterWith(#format: String, timeZone: NSTimeZone = NSTimeZone.localTimeZone(), locale: NSLocale = NSLocale(localeIdentifier: "en_US")) -> NSDateFormatter {
        let key = "\(format.hashValue)\(timeZone.hashValue)\(locale.hashValue)"

        if let cachedDateFormatter = cachedDateFormatters[key] {
            return cachedDateFormatter
        }
        else {
            let newDateFormatter = NSDateFormatter()
            newDateFormatter.dateFormat = format
            newDateFormatter.timeZone = timeZone
            newDateFormatter.locale = locale
            cachedDateFormatters[key] = newDateFormatter
            return newDateFormatter
        }
    }
}

Use the CachedDateFormatter singleton to instantiate any NSDateFormatter object you need. The formatterWith function returns a NSDateFormatter object and stores it in a dictionary based on format string, time zone and locale for future use. If another part of the app needs a date formatter with those same values it’ll get the cached version.

Usage from Swift

let dateFormatter = CachedDateFormatter.sharedInstance.formatterWith(format: "yyyy-MM-dd'-'HHmm", timeZone: NSTimeZone.localTimeZone(), locale: NSLocale(localeIdentifier: "en_US"))

Since Swift allows for default argument values you can omit the second and/or third argument. A minimum call that defaults to the local time zone and “en-US” locale would look like…

let dateFormatter = CachedDateFormatter.sharedInstance.formatterWith(format: "yyyy-MM-dd'-'HHmm")

Usage from Objective-C

Objective-C doesn’t support the concept of optional arguments so it must always be called with all three arguments in Objective-C.

NSDateFormatter *dateFormatter = [[CachedDateFormatter sharedInstance] formatterWithFormat:@"yyyy-MM-dd'-'HHmm" timeZone:[NSTimeZone defaultTimeZone] locale:[NSLocale localeWithLocaleIdentifier:@"en-US"]];

It might be overkill for smaller apps but could come in handy for larger code bases. 

Here's an app on the App Store that makes use of the teachings here:

Comments

Popular posts from this blog

What is .csp extension? C++ Server Pages

C++ Server Pages C++ Server Pages (CSP) is a Web Engine for advanced Web Application Development, that uses blended Markup Language / C++ scripts ( such as HTML/C++, XML/C++, WML/C++ etc.) Similar to ASP and JSP, it provides a great easiness in creating web pages with dynamic content, as well as complex business applications. However, instead of Java, Javascript or VBscript, it uses C++ . This brings some significant advantages: Incredibly high processing efficiency. Benchmarks have shown a range of 80 to 250 times higher processing speed than ASP. The use of pure C++ allows the use of tons of libraries that are currently available. It is important to notice that the libraries written in C++ are tens or hundreds of times more than in any other language. It is widely accepted that the most skilled programmers in the IT market are the C++ ones. However, CGI, ISAPI and other frameworks where C++ applies, do not provide the web developer with facilities for efficient app...

Valid styles for converting datetime to string

I wrote this little table and procedure to help me remember what style 104 did, or how to get HH:MM AM/PM out of a DATETIME column. Basically, it populates a table with the valid style numbers, then loops through those, and produces the result (and the syntax for producing that result) for each style, given the current date and time. It uses also a cursor. This is designed to be a helper function, not something you would use as part of a production environment, so I don't think the performance implications should be a big concern. Read more »