alloc-init objects within +(void)initialize method to reuse them multiple times
-
06-06-2021 - |
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.
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.