Proper retention of object using NSObject load method - ios

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 +load method and object retention does not fit with your usage here, and the reason of your crash)
Loading the singleton instance in the +load method is useless, as it is best to allocate the instance only when needed, that is when it is first requested (lazy loading)
But more important, returning an autoreleased instance in the sharedSettings method 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 #autoreleasepool used). That's very likely to be the cause of your crash!
The implementation of dealloc is useless, first because it only call its super implementation (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.
And last but not least, your implementation is not thread-safe at all.
Of course, normally you need to balance alloc and init calls with release or autorelease calls. 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/retainCount methods, 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:
#implementation ApplicationSettings
+(ApplicationSettings*)sharedInstance
{
static ApplicationSettings* sharedInstance = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; });
return sharedInstance;
}
#end
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 configureInitialSettings method, simply do it in the init method 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 NSFileManager for example).

Related

Objective C - Creating singleton using shared instance

I have doubts regarding the creation of singleton class in Objective-C/iOS.
Where ever I see the trick to create a singleton class in objective-C is this code
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
Whenever I call [MyManager sharedManager] of course I get the same address. However, I can also write [MyManager new] in which case the address is different.
1.Isn't the concept of singleton class is that it restricts the instantiation of a class to one object?
2.If we can create another object its not a singleton anymore, is it?
In my iOS app I tried [UIApplication new]. I got an exception in runtime. Now this I get. You cannot make another instance of UIApplication since its a singleton class.
So why the use of shared instance considered to be the way of creating a singleton class or have I got this all wrong?
The sharedManager is the convenience method you'd use to access the singleton instance. While this doesn't guarantee that there will be only one instance of that manager over the app, if everyone is using sharedManager then there will practically exist only one instance of that manager.
This kind of singletons are singletons by convenience, not by implementation. You should use them, for multiple reasons:
you can unit test them, by calling alloc init in your unit tests and making use of that brand new allocated object
it makes your life easier if decide to later refactor the manager and no longer use it as a singleton if you consider it from the begging like a regular object to work with
Of-course, you can make a singleton by-the-book by overriding the init and allocWithZone: to either return the only instance or by raising an exception, however I'm not sure they'd worth the effort.
There's a very good tech talk regarding singletons held by Misko Hevery in the Google clean code talks playlist, the link to the video: here. This kind of singletons are referred as lower case S singletons, not capital S ones in the video, and Misko explains very well why they are preferred.
It doesn't break singleton concept. You choose your way to implement what you want. If you want to create only singleton instance, you can make run error by override init function:
[NSException exceptionWithName:NSInternalInconsistencyException
reason:#"bla bla bla..." userInfo:nil];
or
you can override it to force return to shared instance.
Of course, you can. But it not recommend if you are using singleton.
Objective-C uses a pragmatic approach. Your +sharedManager method returns a singleton. If someone is stupid enough to call [SingletonClass new] or [[SingletonClass alloc] init], that's their problem. They'll get what they deserve. There is no reason to prevent people from shooting themselves in the foot if that is what they want to do.
There are millions of programming errors that people can make and that the developer of a class or the compiler cannot prevent. No point wasting effort on preventing this particular error.

ObjC How to dispose of a Singleton Object when the app is NOT quitting

My (iOS7 / ARC) app has the concept of "log in" where a user connects to a remote server. For the duration of the users logged-in session, I have some singleton objects to handle low level aspects (sockets, process incoming messages, etc). When the user logs out, I would like to dispose of these singletons and then recreate them when the user logs back in (assumed is the app is not dying off or being quit).
The singleton is created so:
static MYChatMessageManager *messageManager = nil;
static dispatch_once_t onceToken = 0;
+(MYChatMessageManager *) messageManager
{
dispatch_once(&onceToken, ^{
messageManager = [[self alloc] init];
// Do any other initialisation stuff here
});
return messageManager;
}
and I defined a class method which I thought would accomplish the task
+(void) shutdown
{
onceToken = 0;
messageManager = nil;
}
When I call this, I would expect that the -dealloc method of the singleton instance to be called since ARC should see no one has reference to it. However, -dealloc is not being called and in the debugger, after the +shutdown is called, I stop the app (shutdown has run and several seconds late I just stop the app) and examine the object at the memory location I have for messageManager (gotten from lldb earlier, not in code) and it still has a retainCount of 1. I can identify no place in my app that any variable or object pointer is assigned this object which would increment the retain count through ARC.
I am not sure what I can do to make this singleton go away.
Use the Allocations Instrument, turn on reference event tracking, and then see what is holding the final reference(s).
Which you have done, more or less (found the last reference at least).
However, this is bad design and the code is buggy. First, as noted in comments, a dispatch_once_t cannot be reset.
Secondly, and the bigger issue, you should never destroy a shared instance and, by implication, there should be no critical logic in the class's -dealloc method (which, btw, is more of a general rule than one specific to shared instance classes).
By the definition of "shared instance", that object should stick around forever. If it needs to transition between "active" and "shutdown" states, then add that logic in a fashion that does not connect it to the object's lifespan.
There was a sneaky block handler based reference to the object that a third review of the code uncovered. Sorry for the false alarm.

Objective-C singleton pattern in iOS 5+

I've been reading a lot of threads and blog articles about how to implement a singleton in objective-c, several of them maybe being a bit deprecated (year 2010 or earlier), and it seems like people have different opinions regarding this issue... Does Apple have documentation about implementing a singleton? I couldn't find it. If so, could somebody tell me where?
I need a singleton for a class that has some both public and private variables. Currently, this is the implementation I have for such class:
#interface MySingleton ()
#property (strong, nonatomic) NSString *state;
#end
#implementation MySingleton
#synthesize state = _state;
#synthesize count = _count;
static MySingleton *sharedObject = nil;
+ (MySingleton *)sharedInstance
{
static dispatch_once_t _singletonPredicate;
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
return sharedObject;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [self sharedInstance];
}
Should be this the recommended way? And how should I initialize the instance variables, public and private?
Another issue I'd like to make clear about singleton is: will this generate a memory leak? Is the use of singletons actually recommended in iOS?
Thanks
The above is correct, along with #miho's comment about includng the static object inside of the sharedInstance method. But there is no reason to override +allocWithZone:. Singletons in ObjC are generally "shared," not forced. You're free to create other instances of a "singleton." If it's illegal to create other instances, then you should make init perform an NSAssert rather than fooling the caller in +allocWithZone:. If your singleton is mutable (and most are), you absolutely should not override +allocWithZone: this way.
Another issue I'd like to make clear about singleton is: will this generate a memory leak?
No. This object will never be released, but it will always be accessible. That is not a leak.
Is the use of singletons actually recommended in iOS?
Yes, and it is a very common pattern, used all over the Cocoa frameworks. That said, there are various other patterns that have started to recently become somewhat popular among developers. Dependency Injection is getting some interest, though I don't see it in practice very often. Reducing your reliance on singletons can improve testability, and I have been experimenting recently with how to eliminate some of them in my code with some success. But they have a long, proud history in Cocoa, and I do not consider them a problem.
EDIT: you have one actual bug in your code. You should be calling [[self alloc] init], not [[super alloc] init]. There's no reason to ever call +allocWithZone:, just use +alloc. (The time when ...WithZone: methods were useful has long passed.)
In Xcode, under 'Search Documentation' enter Creating a Singleton Instance. There are lots of results (but the link above, at the bottom of the page, has example code).
Yes, this is the recommended way. There is only one small difference of how I use it: I define the sharedObject as static variable inside the + (MySingleton *)sharedInstance method, because it shouldn't be possible to access the variable from anywhere else then from the getter method.
And no, you won't create a memory leak. When your app is terminated all reserved memory used by your app will be released anyway and there is no other situation where a static shared instance should get released. In pre-ARC area it even was common to override the release method do prevent accidentally releasing of the object.
A bit of warning using gcd for singletons:
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
if the init method for some reason addresses the singleton object directly or indirectly, there will be a deadlock. For this reason I believe that the more appropriate way to write a singleton is through the
+ (void) initialize
method
I am still using the singleton header thingy from CocoaWithLove - may be a bit dated but still works like a charm. It basically does the same as described here referring to Apples documentation and I would assume at least Apple's documentation (bottom of this page) is still valid. There are people assuming it will stay valid indefinitely sine it is the official solution Apple suggested.

Class retain counts

Plenty is posted here about avoiding retain cycles with blocks, but what about when using classes and class methods? Say I have a class like this:
// MyClass.h
+ (void)doSomethingAsynch:(void (^)(void))block;
+ (void)doSomethingElse;
and callers would like to say this:
[MyClass doSomethingAsynch:^{
[MyClass doSomethingElse];
}
Must the caller declare an unsafe_unretained copy of MyClass? Or is a class like a singleton, which won't increase it's retain count? Does it matter if we send a class's retain count to the moon since we want it to exist all the time anyway?
[[NSObject class] retainCount] returns NSUIntegerMax, so, yes, classes are implemented as singletons and probably override release as a no-op.
Addendum:
In the objc runtime implementation of NSObject at line 1659 you find ...
+ (id)retain {
return (id)self;
}
... which verifies that [NSObject retain] does nothing.
As you suggest, classes are never going to be deallocated by the system, so it hardly matters if you retain them repeatedly and never release them. My guess would be that retain on a class does nothing.
You are exposing those methods as static/class methods (the '+' at the front instead of a '-' for instance methods), so of course you never need to do [[MyClass alloc] init] for this particular class if you only want to use those methods. Since you're not using alloc, you don't have to worry about retain or release.
These days with ARC (Auto Reference Counting) you mostly don't have to worry about retain and release anyway, it adds all that at compile time for you.
EDIT: stressed mostly, as there are times when you still need worry about it, also added some clarity

Using [NSObject load] to initialized system with no autorelease pool

I am writing an iPad application using the Xcode 4.3.2 and the iOS simulator. I have a series of classes that I want to register with a singleton at start up so that other classes can request services through that singleton that are provided by these registered classes.
To effect this behavior I have been relying on overriding the load class method on NSObject. However, I discovered that all the code that gets executed by the load method occurs outside the main function before there is any opportunity to set up an autorelease pool. I'm using some 3rd party technology in my application that current prohibits the use or automatic reference counting, so I need to rely on an autorelease pool to help manage the lifetime of created objects.
During the registration process, a number of messages appear in the debug console for the simulator complaining about autorelease being called with no autorelease pool. One of these is related to a dictionary allocated by the singleton. Other are related to block objects that get copied from the stack and store in that singleton dictionary.
It is not clear to me how serious these debug messages are. I suspect the allocation of the dictionary may not be problematic as the singleton should exist for the lifetime of the application and that dictionary will likely never be released. Likewise the block stored in the dictionary should persist as well, so I'm wondering if I don't need to bother calling autorelease on them after calling the copy method.
Or maybe there is another way to accomplish what I want with out having to resort to the current technique that might be less problematic
What can people suggest about this issue?
You should have better luck overriding +[NSObject initialize] rather than load, initialize is called the first time the class is referenced, rather than when the image the class is in is loaded. This will give you better handing of all this.
A good approach is to use dispatch_once_t, which is only executed once per runtime, across all threads:
+ (id)sharedInstance
{
static dispatch_once_t once;
static SingletonClass *sharedInstance;
dispatch_once(&once, ^ { sharedInstance = [[self alloc] init]; });
return sharedInstance;
}

Resources