Question

I'm using a NSDateFormatter object (customized for specific purposes) multiple times. Since I'm not a objc expert, I figured out three different approaches to deal with it.

In the first one, I've created a NSDateFormatter category and customized the code there. This is common approach but each time I create such an object, this is put in the main autorelease pool. This behaviour, I think, is valid both for non-ARC and ARC code.

In the second instead, I've overridden the +(void)initialize method and put the customization code there. Here a simple example:

static NSDateFormatter* dateFormatter = nil;

+(void)initialize
{
    dateFormatter = [[NSDateFormatter alloc] init];
    // other code here
}

Finally, I set up a third approach using a lazy loading instantiation through properties like the following:

-(NSDateFormatter)dateFormatter
{
    if(dateFormatter) return dateFormatter;        
    // alloc-init here
}

Said this, I would like to know what approach is the most suitable to deal with objects multiple times and if, using +(void)initialize in that manner, is correct.

Thank you in advance.

Was it helpful?

Solution

Both later methods are correct, but I believe you want to put them together!

static NSDateFormatter *sharedInstance = nil;

+ (NSDateFormatter *)sharedInstance {
    if (sharedInstance == nil) {
        sharedInstance = [[NSDateFormatter alloc] init];
    }
    return sharedInstance;
}

Note: Such classes are called singletons. Read more

OTHER TIPS

Essentially, my favourite pattern is the one that mindw0rk has already given (I have up voted his answer). It has the advantage that you can put the method in a category on NSDateFormatter. I would modify it slightly thusly:

+ (NSDateFormatter *)sharedInstance {
    static NSDateFormatter *sharedInstance = nil;
    if (sharedInstance == nil) {
        sharedInstance = [[NSDateFormatter alloc] init];
    }
    return sharedInstance;
}

so that you can't inadvertently reference sharedInstance without initialising it first.

If you have more than one shared instance, you can have a different method to get each one e.g.

+ (NSDateFormatter *)dateFormatterForFoo {
    static NSDateFormatter *sharedInstance = nil;
    if (sharedInstance == nil) {
        sharedInstance = [[NSDateFormatter alloc] init];
    }
    return sharedInstance;
}

+ (NSDateFormatter *)dateFormatterForBar {
    static NSDateFormatter *sharedInstance = nil;
    if (sharedInstance == nil) {
        sharedInstance = [[NSDateFormatter alloc] init];
    }
    return sharedInstance;
}

Or if each customised date formatter has its own subclass, they can each implement +sharedInstance to give back an object of the right class.

Or you can have a dictionary of date formatters:

+ (NSDateFormatter *)customisedFormatterForKey: (NSString*) key {
    static NSDictionary *sharedInstances = nil;
    if (sharedInstance == nil) {
        sharedInstance = [[NSDictionary alloc] initWithObjectsAndKeys: ....];
    }
    return [sharedInstance objectForKey: key];
}

I have some comments on the -initialize approach.

You have to be a little bit careful about using -initialize. It's invoked once just before first use of the class. If you never use the class, it will never get invoked. So for your code to work, you have to make sure you send a message to NSDateFormatter or an instance of NSDateFormatter before you start using the shared instance dateFormatter. Note that sending a message to dateFormatter itself doesn't count. This is because it starts out nil and therefore doesn't have a class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top