I’m not quite sure where I’m going wrong with this implementation and what adjustment I need to make so that the loaded singleton stays in memory.
@implementation ApplicationSettings
static ApplicationSettings *sharedSettings = nil;
+ (void)load
{
@autoreleasepool {
sharedSettings = [self sharedSettings];
[self configureInitialSettings];
}
}
+ (ApplicationSettings*) sharedSettings {
if (sharedSettings)
return sharedSettings;
else {
return [[[ApplicationSettings alloc] init] autorelease];
}
}
- (void) dealloc {
[super dealloc];
}
The main methods for loading are shown here, along with the dealloc (I’m not using ARC).
I have started using this pattern recently. I’m going to have to check each implementation to make sure it’s right. I found one case where it is being deallocated and causing a crash. Obviously the @autoreleasepool owns it. Should I remove the autorelease in the return statement so it doesn’t go into the autorelease pool? If I do that, then it’s retained until the program is killed, which is fine with me. Is there anything wrong with that?
That’s not the correct way to declare a singleton class. (And as a result, your
+loadmethod and object retention does not fit with your usage here, and the reason of your crash)+loadmethod is useless, as it is best to allocate the instance only when needed, that is when it is first requested (lazy loading)sharedSettingsmethod make the singleton pattern invalid and fail its purpose, as you return an instance that will be released as soon as the autorelease pool will be drained (that is at the end of the current RunLoop iteration — if not sooner if you have any inner@autoreleasepoolused). That’s very likely to be the cause of your crash!deallocis useless, first because it only call itssuperimplementation (so you can avoid the whole method definition), and because as your class is meant to be a singleton, the instance will never be released from memory while your app is alive.Of course, normally you need to balance
allocandinitcalls withreleaseorautoreleasecalls. That’s the main rule of memory management. But for the Singleton Pattern, as per definition the shared instance of a singleton lives as long as the application live (that’s is main role), this is the exception to the rule, and you should not release your sharedInstance that holds your singleton object, to make sure it keeps living and is not deallocated from memory.One correct (legacy) implementation for a singleton without ARC would be to overload the
alloc/retain/release/autorelease/retainCountmethods, as explained in the Apple documentation about singleton. But in fact that’s not really the way we do it anymore these days, as this documentation is quite old (was written before GCD existed) and obsolete, and as GCD now offers a way better alternative, that is guarantied to be thread-safe, and is compatible with both non-ARC and ARC too (whereas the latter is not possible to implement under ARC environment). So here it goes:And that’s all. No need for a global variable outside of the method or whatsoever. Simply declare this method and use it every time you need access to the singleton and you’re done.
And if you need to fill some instance variables of your singleton then, like what you probably do in your
configureInitialSettingsmethod, simply do it in theinitmethod of your singleton, as you would do in a standard class as usual.Additional Note: If you want to be really strict, some may argue that it will not forbid the allocation/creation of other instances of the class using alloc/init (and neither do your own implementation in your question) so that is not a real singleton: one can still allocate multiple instances of it if s/he really wants to.
But in practice even if that’s true, I don’t see any reason why to really add these constraints (and if you switch to ARC one day, you can’t add these constraints anyway). What you really want when you seek for the Singleton Pattern is more “a common instance shared accross the whole application” than “a way to forbid the creation of multiple instances”, and that’s what we have here. And actually that’s the case for most of the classes that claim to be Singletons (like
NSFileManagerfor example).