1

I'm trying to create a date formatter that lazy loads and is only initialized once. In Swift, if you create a variable globally, it automatically loads lazilly, so that's taken care of. But how do I only create it once, in a thread-safe manner? I found this obj-c code:

(NSDateFormatter *)formatter {
  static NSDateFormatter *formatter;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    _formatter = [[NSDateFormatter alloc] init];
    _formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
  });
  return formatter;
}

But I'm having trouble re-creating this in Swift, since static variables can only be declared on a type, not a computed property or function. Does this mean I can only re-create this as a class?

EDIT

I know how to create a singleton as a class, I was more wondering if there were a simpler way to use a singleton (global computed property vs class). But on second thought a class is probably better anyway, and its singleton implementation is very simple.

Ryan Bobrowski
  • 2,641
  • 3
  • 31
  • 52

1 Answers1

2

I guess something similar can do the job for you:

func formatter() -> NSDateFormatter! {
    struct myStatic  {
        static var dateFormatter: NSDateFormatter? = nil
        static var token: dispatch_once_t = 0;
    }
    dispatch_once(&myStatic.token) {
        myStatic.dateFormatter = NSDateFormatter();
        myStatic.dateFormatter?.dateFormat = "EEE MMM dd HH:mm:ss Z yyyy"
    }
    return myStatic.dateFormatter;
}

or alternatively:

lazy var formatter: NSDateFormatter = {
    let dateFormatter: NSDateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "EEE MMM dd HH:mm:ss Z yyyy"
    return dateFormatter
}()
holex
  • 23,961
  • 7
  • 62
  • 76
  • ...or see the _possible duplicate_ link. I just saw that comments about someone has already solved that issue somewhere else after I posted my answer. – holex Jun 08 '15 at 14:18
  • About the alternative: computed properties are computed every time they're called, no? That would mean I'm reinitializing NSDateFormatter each time, which is an expensive operation. – Ryan Bobrowski Jun 08 '15 at 20:11
  • this `lazy` property is inited only _once_ in its lifetime, before the very first use. – holex Jun 09 '15 at 07:53
  • `lazy` means they are initialized when they're first used, yes - but that's it. I just tested it out and computed properties are re-calculated each time you call them, lazy or not (sidenote: global properties are lazy by default, so that keyword isn't necessary in that case). Anyway, the second option wouldn't be valid because it would be reinitializing NSDateFormatter() each time – Ryan Bobrowski Jun 09 '15 at 08:22
  • @itstrueimryan, I'm not sure what you are actually talking about at the moment; the `lazy` property is created only once in their lifetime, and every time you access to that property you will get back _the same instance_ which was inited at the first time – or if you'd like: the `NSDateFormatter` will not be inited each time, but obviously if you have a class which instantiated multiple times, every individual instance has its _own_ instance of their `lazy` properties. maybe, that scenario confuses you. – holex Jun 09 '15 at 11:49
  • Can you link to a source for that? Maybe you're right and I'm just out of it - I am somewhat newish to this iOS stuff. But I just can't find that anywhere. I know this is a tangent but I'm just curious. – Ryan Bobrowski Jun 09 '15 at 17:09
  • @itstrueimryan, look, that is the obvious behaviour and key purpose of `lazy` properties, they are inited __only once__: before their first use. however you can read much more about properties in _Swift_ in [Apple's documentation](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html). – holex Jun 10 '15 at 08:05
  • Lazy properties, yes. But a lazy computed property, like the one in your example, is different. Yes, it's initialized before its first use, but it's recalculated each time it's called. – Ryan Bobrowski Jun 10 '15 at 16:23
  • @itstrueimryan, I'm not sure how many times I need to tell you about the `lazy` properties: they are inited _only once_. please, try to accept this very simple fact about `lazy` properties because the way, how we init a `lazy` property, will not change the fact of they are inited _only once_. ok? :) – holex Jun 10 '15 at 16:35
  • Alright so I misread and realized that your second example had an = so it's a closure and not a computed property...but I did say computed property like 100 times and you couldn't correct me? Sheesh. While we're on that subject, even though it's not relevant anymore: lazy is not allowed on computed properties so they are computed every time, which is all I was saying: http://stackoverflow.com/questions/24177908/swift-is-correct-to-use-stored-properties-as-computed-properties – Ryan Bobrowski Jun 10 '15 at 16:56
  • @itstrueimryan, you insisted to talk about computed properties whole time. :) if you need to know more about Swift language or its syntax, please visit the [official site](https://developer.apple.com/swift/). – holex Jun 10 '15 at 20:32