Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one create a 'static' in a Swift class extension?

In several places here, it has been suggested that using a computed property within an extension of NSDate might a good way to obtain a string version of a date via a NSDateFormatter, like so:

extension NSDate {
    public var UTC : String {
        let formatter = NSDateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
        formatter.timeZone = NSTimeZone(abbreviation: "UTC")
        return formatter.stringFromDate(self)
    }
}

However, allocating a NSDateFormatter is expensive and it is suggested that they be created once and cached. The above code creates the NSDateFormatter every time a date is formatted, and I'm wondering if there is a way to create the NSDateFormatter once inside the extension for reuse?

Obviously, I could create it just once outside the extension, but that seems to defeat the encapsulation that characterizes classes.

I am reminded of: https://xkcd.com/1179/ !!

like image 675
Ramsay Consulting Avatar asked Nov 09 '15 05:11

Ramsay Consulting


People also ask

How do I create a static variable in Swift?

You create static variable by appending static keyword in front of your variable declaration. We will be using playground to explore more. When we define any variable as let, it means it's values cannot be modified, On the other hand if we define any variable as var it means it's values can be modified.

Can we write extension method for static class?

An extension method must be defined in a top-level static class. An extension method with the same name and signature as an instance method will not be called. Extension methods cannot be used to override existing methods. The concept of extension methods cannot be applied to fields, properties or events.

How do I create a class extension in Swift?

Creating an extension in Swift Creating extensions is similar to creating named types in Swift. When creating an extension, you add the word extension before the name. extension SomeNamedType { // Extending SomeNamedType, and adding new // functionality to it. }

What is a static class Swift?

Swift allows us to use a static prefix on methods and properties to associate them with the type that they're declared on rather than the instance. We can also use static properties to create singletons of our objects which, as you have probably heard before is a huge anti-pattern.


1 Answers

You can add static members to class extensions just the same as on classes. You need to prefix the class name to the static member name when you use it, e.g. NSDate.dateFormatterUTC, even if you’re using it in the same class.

This works:

extension NSDate {
    private static let dateFormatterUTC: NSDateFormatter = {
        let formatter = NSDateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
        formatter.timeZone = NSTimeZone(abbreviation: "UTC")
        return formatter
    }()

    public var UTC : String {
        return NSDate.dateFormatterUTC.stringFromDate(self)
    }
}

It’s also not the worst thing in the world just to use a private constant:

private let dateFormatterUTC: NSDateFormatter = {
    let formatter = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
    formatter.timeZone = NSTimeZone(abbreviation: "UTC")
    return formatter
}()

extension NSDate {
    public var UTC : String {
        return dateFormatterUTC.stringFromDate(self)
    }
}

This is not significantly worse than the static class member, because Swift’s private is file-private, not type-private. These two declarations of dateFormatterUTC have the same scope. Even in the first example, NSDate.dateFormatterUTC is accessible throughout the entire file it’s declared in.

I do agree that the static version is preferable, but for stylistic reasons only: I like the way it’s indented right next to the thing that uses it.

As Gwendal wisely notes above, this approach assumes UTC will only ever be called from one thread. Although static let and global let are both thread-safe in Swift, the NSDateFormatter class is not! Looks like it’s threadsafe starting in iOS 7. Phew.

Still, always good to keep a thread safety warning next to any mention of singletons. If you do want to use a non-threadsafe helper object from multiple threads, consider either creating a new helper on every call, or using NSThread.currentThread().threadDictionary to create a per-thread instance. Be sure to do a little profiling to make sure you’re actually solving a performance problem before opting for the more complex thread-local option.

like image 177
Paul Cantrell Avatar answered Oct 05 '22 11:10

Paul Cantrell