Possibilities of Singleton instance getting deallocated automatically - ios

I am creating singleton instance as below:
+(MySingleton*)sharedInstance {
static MySingleton sharedObject = nil;
static dispatch_once_t predicate = 0;
dispatch_once(&predicate, ^{
sharedObject = [[MySingleton alloc] init];
});
return sharedObject;
}
What are the possibilities of sharedObject getting deallocated automatically?
How can I be sure that sharedObject will remain in memory until app is terminated?

As another answer rightly points out, this shared singleton will never be deallocated. There are two parts to answer "why", both of which come from the following line:
static MySingleton * sharedObject = nil;
First, static. static, when used inside of a function like this, modifies the lifetime of a variable, changing it from automatic, the implicit default, to static. This means that this variable exists for the entire lifetime of the program.
Second, this declaration makes sharedObject a strong reference. Variables in Objective-C are strong by default, but to be pedantic, you could have written:
static __strong MySingleton * sharedObject = nil;
So: we have a variable that lives for the entire duration of your program (static), and that maintains a strong reference to the object it represents (__strong). With these two pieces of information, plus the fact that you never change the object to which the variable points, you can deduce that sharedObject will never be deallocated.

0 possibility. It will never be released, static keeps it with strong reference. In ARC world you can't just release something without first retaining it.

I ran into one very dubious case where it can get released and cause unhappy problems, so while uncommon something to be careful of.
If a you pass its memory address a third party low level library ie. as user_data (or perhaps a low level c library you have created) and that library releases the memory. You would not expect external libraries to release user_data you provide but that was the case with a web sockets c library I was using.

sharedObject will be released after its included functions complete and after releasing contained blocks. so that, dispatch_once most probably releases running block after run it once. it means, it will be released just after called onece.

Related

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.

Where should I release static local and global variable with ARC?

I just created a new class in my project, subclass of UITableViewController and noticed that in the method tableView:cellForRowAtIndexPath: template, Apple still provide a static local NSString to use as a cell identifier.
I know that for static global/local variable we need to assign nil cause it's considered as strong.
So I asked myself the question : Where should I assign nil to static global variable ?
And static global variable ?
Thanks for the answers guys
A short answer to the "where should static global variables be released" is "nowhere".
Long answer goes like this: when you make a variable static or global, you want it to exist regardless of any instances of your classes coming into existence or being released. Simply speaking, you want your statics to always be there for you. Therefore, the only reason to release them would be if your program is about to exit. But if your program is exiting anyway, you might as well let the operating system handle the cleanup for you, and forget about releasing your global and static variables.
Note, however, that the use of static and global variables should be an exception, not a norm. You use them for a good reason, and exercise your best judgement to decide what should be static. Moreover, you should avoid referencing collections of non-static variables from static ones through a strong reference, because otherwise you may create hard-to-find memory leaks.
There is nothing wrong with a static local for the NSString used as your cell identifier: it takes very little memory, and it does not grow, so it's not a big deal that it is not released at the end of your program's run.
You don't need to do it, it will never be released and its ok since it is a global.
In ARC will be treated as strong for default and its lifetime it is equal to the application lifetime.
Static strings are a special case, and don't need to be released.
static variable, means it holds a strong reference to the object it points to.
static MyClass *var;
var = [MyClass instance];
Now var always holds strong reference to the above allocated object.so it will never be removed from memory.
But after some condition you no longer need that object,then simply
var =nil would work.
because now var points to nil and no longer points to created object.so that object will be deleted from memory.

How long does an autoreleased static object declared globally, survive in memory?

If I declare a static object handle in a class file in global scope. And the object assigned to this handle is an autoreleased one. Then for how long will this object remain in memory during my application life cycle ?
If I declare a static object handle in a class file in global scope. And the object assigned to this handle is an autoreleased one. Then for how long will this object remain in memory during my application life cycle?
Short Answer: You want your global to be a strong reference. In MRC, you must add the retains and releases for globals. In ARC, the global is implicitly strong (and ARC adds them for you).
Long Answer:
Under ARC, your static global variable is a strong reference. In MRC, you would retain such a variable when set and then release the previous object. If you did not, then you could still access it after it were deallocated (dangling pointer).
Because it is a strong reference, your object will remain valid until a) the strong reference by the global variable is given up and b) the autorelease pool is drained c) and of course any other strong references are given up.
So if you are using strong references for that global and you never reassign it (logically, giving up the global's strong reference), then your object would never be dealloc'ed.
When you use unsafe nonretained semantics (by decoration in ARC, or the default for a static in MRC), the object would be -dealloced when the current autorelease pool is drained and all strong references are removed. This is easiest to illustrate with a program (MRC);
static MONObject * GlobalObject;
//
// In MRC, you must add the reference counting to ensure you do not end up with a dangling
// pointer, so false is what how your program should be written in MRC.
//
// In ARC, your program will look like NonRetainedOwnership because it treats the global
// as a strong reference.
static const bool NonRetainedOwnership = ...T/F...;
...
// assume GlobalObject is accessed from one thread only -- i won't bother with
// the supporting code to illustrate how this should be made thread safe.
- (MONObject *)sharedObject
{
if (nil == GlobalObject) {
if (NonRetainedOwnership) {
// don't do this! lifetime will be determined by strong client references
// and the reference you rely on now will be lost when the thread's current
// autorelease pool is drained -- leaving you with a dangling pointer which
// will cause issues when -sharedObject is called again.
GlobalObject = [[MONObject new] autorelease];
}
else {
// Good - keep a strong reference:
GlobalObject = [MONObject new];
}
}
return GlobalObject;
}
- (void)disposeSharedObject
{
if (NonRetainedOwnership) {
GlobalObject = nil;
}
else {
// remove our reference, which was established at [MONObject new]
// assuming there are no strong external references, the object
// will be dealloc'ed -- but you should not make that assumption
// if you return it.
[GlobalObject release], GlobalObject = nil;
}
}
So if NonRetainedOwnership is true and you use MRC, then your object would typically be -dealloc-ed shortly after -sharedObject returns (assuming whoever called -sharedObject holds no strong reference). In this case, 'shortly' means the pool will often be drained a few frames back in your current callstack, often in AppKit or UIKit when you are on the main thread since I don't see many people explicitly create autorelease pools on the main thread. borrrden said after "1/60th of a second", and the assumption there is that the object is created and autoreleased in the main thread's run loop (correct me if I am wrong). The 'Kits create autorelease pools at each iteration of the main run loop, but your program could be running on a secondary thread or there could be an inner autorelease pool, so the lifetime has the possibility to be shorter or longer. Normally, you don't need to think about these things in much depth -- just use a strong reference here since you really have no other way to ensure the right thing happens with this global variable.
If you simply wrote: #autoreleasepool{[[MONObject new] autorelease];} NSLog("Hi"); then the object would (under normal circumstances) be released by the time NSLog were called.
The declaration of variable doesn't matter as such, The thing what matters is when did you assigned an autoreleased object to it, If it is assigned under any autorelease pool than it would drain it else it would be released on program termination by autorelease pool in main method!
The Variable is just a pointer and does not retain the object unless done explicitly, thats why retaining static objects is preferred: Why retain a static variable?
When the pool is 'drained'. This may not happen right away.
Please see a similar question
It depends. If the variable is initialized only once, and should stay around for the lifetime of the application, then no, it shouldn't be released (its memory will essentially be freed when the application exits, anyway). If, however, the value of the static variable changes, then yes, the previous object should be released when the static variable is set to a new object.

Proper retention of object using NSObject load method

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).

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