How do I dispose of my own sharedInstance in Objective-C? - objective-c

If I have a class that has a sharedInstance of itself (singleton pattern) or a shared instance of another class, how do I make sure that shared instance is released properly when my program exits? Better yet, can you point me to some documentation about this?
sample class (with all other methods removed for clarity):
#interface Foo : NSObject {
}
+ (Foo*)sharedInstance;
#end
the .m file:
static Foo* SharedInstance;
#implementation Foo
+ (Foo*)sharedInstance
{
if (!SharedInstance)
SharedInstance = [[Foo alloc] init]; // possible memory leak?
return SharedInstance;
}
#end
In the above code, when can I release SharedInstance?

Unless there are resources beyond the shared instance that need to be released (e.g. files, notifications at cleanup etc.), you can just let the memory for sharedInstance be cleaned up at application exit. Even files and network sockets etc. will be cleaned up by the OS at application exit, so you could get away not cleaning up those as well.
If you do have clean-up actions that need to be taken before application exit, you'll have to add a cleanup or somesuch method to your shared instance and a static method to release the shared instance.

Usually there is no need to clean up anything on exit as Barry pointed out, but what you can do is setting an NSApplication delegate that implements
- (void)applicationWillTerminate:(NSNotification *)aNotification
This method is then called right before your application is going to quit. In this method you can call some static method of your shared instance classes to clean up the internally cached shared instance.
However, something like a memory leak beyond application quit doesn't exist. If your application terminates, all memory it ever owned is given back to the system no matter how it was allocated. If that was not the case and your application was going to crash, the memory it used before the crash would be ultimately lost to the system and that is not acceptable. On a multi-tasking OS, an application that crashes must not have any negative effects on the rest of the system!

Whatever you do, don't autorelease a non-retained shared instance, because it will be free'd, and you will be screwed. Do it the way you are currently doing, but in applicationWillTerminate: put something like this:
BackgroundFactory * factory = [self sharedFactory];
// prevent an analyzer annoyance
NSValue * value = [NSValue valueWithPointer:factory];
id fac = (id)[value pointerValue];
[fac release];
Note that sharedFactory is the method returning a shared instance. All of this code should go into a +freeSharedInstance method.

It is better to do it like this
+ (Foo*)sharedInstance
{
if (!SharedInstance)
SharedInstance = [[[Foo alloc] init] autorelease];
return SharedInstance;
}
#end
Class B which uses the shared instance can retain and release it.

Related

Recipes to implement a self-retained network lib

I would like to implement a self-retained network lib that can be used also with ARC.
The calling code for this lib should be like the following.
- (void)downloadData {
NSURL *url = // alloc-init
NetworkFetcher *networkFetcher = [[NetworkFetcher alloc] initWithURL:url];
[networkFetcher startWithCompletionHandler:^(NSData *data){
_fetchedData = data;
}];
// under ARC it will put a release call for the networkFetcher here
}
This approach is used by TWRequest (if I am not wrong it's deprecated now) class in Twitter framework. The advantage is that the caller does not need to maintain the fetcher alive itself.
Some details. The startWithCompletionHandler copies the block for future reuse. When the request has finished, the fetcheher releases the block settima it to nil.
So, what the approach I need to follow so the fetcher can be self-retained? Any best pratice?
You can add a "private" property
#interface NetworkFetcher ()
#property (strong, nonatomic) NetworkFetcher *selfRef;
#end
in a class extension to the NetworkFetcher class. In startWithCompletionHandler, you set
self.selfRef = self;
to prevent the object from being deallocated. When the request has finished and the completion block has been called, set
self.selfRef = nil;
to destroy the retain cycle.
I usually use the technique described by Martin R which basically imitates the older retain and release but there are also other methods.
You can capture the fetcher in the completionHandler. Just use self anywhere in the completion handler and don't forget to release the block when it has been called. This is a bit less readable then using a property but it follows the same principle
Another method is to have a singleton (mutable) array of active fetchers. Adding/Removing follows the same principle as with self.selfRef property.
With a singleton array there is one big advantage - you can access the fetchers whenever you want - cancel them or just get the number of active fetchers (to limit number of simultaneous downloads, for example).

Accessing NSObject's (superclass) version of allocWithZone while bypassing overriding (subclass) version of allocWithZone

In iOS Programming Book from Big Nerd Ranch (3rd ed) they say on pg.194
..a knowledgeable programmer could still create an instance of BNRItemStore via allocWithZone:, which would bypass our sneaky alloc trap.To prevent this possibility, override allocWithZone: in BNRItemStore.m to return the single BNRItemStore instance.
+(id) allocWithZone:(NSZone *)zone
{
return [self sharedStore];
}
This statement seems confusing to me. Doesn't this following code not prove this wrong in a way-
#import <Foundation/Foundation.h>
#interface BNRItemStore : NSObject
+(BNRItemStore *)sharedStore;
+(id)retrieveObject;
#end
#implementation BNRItemStore
+(BNRItemStore *)sharedStore{
static BNRItemStore *sharedStore=nil;
if (!sharedStore){
NSLog(#"Test2");
sharedStore= [[super allocWithZone:nil] init];
}
NSLog(#"sharedStore-> %#",sharedStore);
return sharedStore;
}
+(id)allocWithZone:(NSZone *)zone{
NSLog(#"Test1");
return [self sharedStore];
}
+(id)alloc{
NSLog(#"Retrieving super object");
NSLog(#"%#", [super allocWithZone:nil]);//Bypassing the subclass version of allocWithZone.
return [super allocWithZone:nil];
}
#end
int main(){
[[BNRItemStore alloc] init]; //the alloc message triggers a call to the subclass (overriding) version of +(id)alloc method
}
The output is:
2013-10-18 18:24:40.132 BNRItemStore[381:707] Retrieving super object
2013-10-18 18:24:40.134 BNRItemStore[381:707] BNRItemStore:0x7f8c72c091e0
If the call [super allocWithZone:nil] inside of subclass 'alloc' method would have triggered a call to subclass allocWithZone,the console would be logging "Test1" and "Test2" and finally would lead to static pointer getting allocated. But this did not happen.
This means that if we directly call [NSObject allocWithZone:nil] or [super allocWithZone:nil], the message would not redirect to the overriding version (subclass version) of allocWithZone but will give direct access to NSAllocateObject() function which does the actual allocation.
The code of +(id)allocWithZone in NSObject must look somewhat like this-
+(id)allocWithZone:(NSZone *)zone{
return NSAllocateObject();
}
Had this implementation(NSObject's allocWithZone:) included something like [self allocWithZone], the message dispatch mechanism would have included the subclass version of allocWithZone which would then make us go through the "sneaky" trap involving a call to sharedStore method.Following is the case that I'm talking about. Now if this were the case the code would definitely have infinite-looped.Clearly this isn't the case.
+(id)allocWithZone:(NSZone *)zone{
if([self allocWithZone:zone]) //this would trigger a call to subclass ver. which would call sharedStore method which would then have [super allocWithZone:nil].Infinite Loop
return NSAllocateObject();
}
So can someone clear up this query about this so called "sneaky" trap. Was the trap meant for blocking anyone from instantiating separately .i.e not being able to use NSObject's allocWithZone except when inside of sharedStore method ? Pls clarify..
The first, most important lesson here is that you should not override +allocWithZone:. I know the BNR book describes it (and the BNR book is generally very good). You shouldn't do it. I know that Apple includes some example code that does it. You shouldn't do it. (And Apple notes in the explanation that it is rare to need this.) Singletons should be created with the dispatch_once pattern.
You don't give the initial code, but I suspect that their example code overrides alloc, but not allocWithZone:. They're simply saying that if the caller uses allocWithZone:, it won't go through alloc, so they've also overridden alloc to catch that. (Of course the right answer would be just to override allocWithZone: and not alloc. But you shouldn't be overriding these methods in any case.)
EDIT:
I believe you are misunderstanding what "our sneaky alloc trap" means here. The author is assuming the following code at this point in the text:
#interface BNRItemStore : NSObject
+(BNRItemStore *)sharedStore;
#end
#implementation BNRItemStore
+(BNRItemStore *)sharedStore{
static BNRItemStore *sharedStore=nil;
if (!sharedStore){
sharedStore = [[super allocWithZone:nil] init];
}
return sharedStore;
}
#end
That's it; no +alloc overrides at all. It then points out "to enforce the singleton status…you must ensure that another instance of BNRItemStore cannot be allocated." (*)
The author goes on to suggest that we might enforce the singleton status by overriding +alloc, but immediately notes that this is insufficient, since the caller can use +allocWithZone: instead. Since it is documented that [NSObject alloc] calls [self allocWithZone:], it is necessary and sufficient to override +allocWithZone: and unnecessary and insufficient to override +alloc.
What you've done in your code is demonstrate that you can modify BNRItemStore to call [super allocWithZone:] in +alloc. That is not the point. If you can modify BNRItemStore, you could also make it a non-singleton. The point is whether an outside caller (main() in your case) can bypass the singleton instantiation, which she cannot. (**)
(*) The point it doesn't make at this point, and probably should, is that it is generally a bad idea to "enforce the singleton status" by quietly returning a singleton when the callers asked you to allocate a new object. If you need to enforce the singleton status, it is better IMO to do so with an assertion in init, since the request for a second allocation represents a programming error. That said, there are times when "transparent" singletons of immutable objects can be useful for performance reasons, such as the special singletons NSNumber provides for certain common integers, and this technique is appropriate in those cases. (By "transparent," I mean that the singleton-ness is an implementation detail that the caller should never worry about. This presumes at a minimum that the object is immutable.)
(**) Actually she can if she is determined to do so. She could always call NSAllocateObject() herself, bypassing +alloc entirely, and then call -init. This would of course be insane, and there is no reason to "protect" her from herself in doing this. It is not the job of an SDK to protect itself from the caller. It is only the job of an SDK to protect a caller from likely mistakes. The caller is never the enemy.
i'm not sure if this quite answers your question or not, but "allocWithZone:" was used back in the day to be able to partition the memory allocated. apple has since moved away from this concept and expects everything to be allocated in the same heap space. "allocWithZone:" does not even function the way it used to, and apple specifically says not to use it.

Detected autorelease objects

I using Test Driven Development in Objective-C for iOS and Mac OS X development, and I want to be able to write tests that can verify that objects I create with class factory methods return autorelease objects.
How can someone write a test that verifies a provided object is autorelease?
In short, you can't. There is no way to know the autorelease state of an object.
In some cases, you can infer whether an object was placed in an autorelease pool. The idea is declaring a pointer to an object, instantiating it within an #autoreleasepool block, and then verifying that it had dealloc called after the end of the block.
Through whatever combination of swizzling or overriding dealloc you choose, you must first provide a way to verify that dealloc has been called. I wrote an NSObject category with the following interface and implementation, that provides a deallocationDelegate property that will receive a message of handleDeallocation: when the object is deallocated.
#interface NSObject (FunTimes)
#property (nonatomic, assign) id deallocationDelegate;
#end
#implementation NSObject (FunTimes)
+ (void)load
{
Class klass = [NSObject class];
SEL originalSelector = #selector(dealloc);
Method originalMethod = class_getInstanceMethod(klass, originalSelector);
SEL replacementSelector = #selector(funDealloc);
Method replacementMethod = class_getInstanceMethod(klass, replacementSelector);
if(class_addMethod(klass, originalSelector, method_getImplementation(replacementMethod), method_getTypeEncoding(replacementMethod)))
{
class_replaceMethod(klass, replacementSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
else
{
method_exchangeImplementations(originalMethod, replacementMethod);
}
}
- (void)funDealloc
{
if (self.deallocationDelegate)
[self.deallocationDelegate performSelector:#selector(handleDeallocation:) withObject:self];
[self funDealloc];
}
static char myKey;
- (void)setDeallocationDelegate:(id)deallocationDelegate
{
objc_setAssociatedObject(self, &myKey, deallocationDelegate, OBJC_ASSOCIATION_ASSIGN);
}
- (id)deallocationDelegate
{
return objc_getAssociatedObject(self, &myKey);
}
#end
I ran some test code in my application delegate just to see if it works. I declared an NSMutableArray instance designed to hold NSValue instances derived from the pointers of objects calling -handleDeallocation, which I implement as shown:
- (void)handleDeallocation:(id)toDie
{
NSValue *pointerValue = [NSValue valueWithPointer:toDie];
[self.deallocatedPointerValues addObject:pointerValue];
}
Now, here's a snippet of what I ran. SomeClass is an NSObject subclass with no additional properties or methods.
self.deallocatedPointerValues = [NSMutableArray array];
SomeClass *arsc = nil;
#autoreleasepool {
arsc = [[[SomeClass alloc] init] autorelease];
arsc.deallocationDelegate = self;
NSValue *prePointerValue = [NSValue valueWithPointer:arsc];
BOOL preDeallocated = [self.deallocatedPointerValues containsObject:prePointerValue];
NSLog(#"PreDeallocated should be no is %d",preDeallocated);
}
NSValue *postPointerValue = [NSValue valueWithPointer:arsc];
BOOL postDeallocated = [self.deallocatedPointerValues containsObject:postPointerValue];
NSLog(#"Post deallocated should be yes is %d",postDeallocated);
In this case, it can be verified that the object pointed to by arsc (which stands for auto released SomeClass) has been deallocated due to ending the #autoreleasepool block.
There are several significant limitations to the this approach. One, this cannot work when other messages of retain may be sent to your object that is returned from your factory method. Also, and this should go without saying, swizzling dealloc should only be done in experimental settings, and I think some would argue that it shouldn't be swizzled in testing (obviously it shouldn't be swizzled in production!). Finally, and more significantly, this doesn't work well with Foundation objects such as NSString that have been optimized in ways that it's not always clear whether you are creating a new instance or not. So this is most appropriate, if at all, for your own custom objects.
As a final word, I don't think it's practical to do this really. I felt it was more work than it was worth and is so narrowly applicable as the make spending time learning instruments better to be a far better investment when it comes to memory management. And, of course, with ARC's ascendency, this approach is archaic from the start. Regardless, if you do have need to write such tests, and can work around the limitations here, feel free to adapt this code. I'd be curious to see how it pans out in an actual testing environment.
I commend your dedication to TDD. But memory management is an area where you simply have to follow well-established conventions: "When returning an object, it needs to take care of its own lifetime." My unit tests catch me when I accidentally over-release something, but they won't catch a leak. For that, I rely first on Analyze, then on running the Leaks instrument.

Should releasing an object and setting it to nil be atomic?

I'm new to Objective C. I see in many iPhone/iPad applications that after releasing an object, it would then be set to nil.
[self.obj release]
self.obj = nil;
I assume this is done so as not to leave the pointer to reference a memory location that is now deallocated. Now assume the following situation:
//Thread #1 code
..some code
..some code
[self.obj release]
-------> Thread #2 runs //Thread #2 code
..some code
if (self.obj){
some code
}
self.obj = nil; <----- Thread #1 runs
I was wondering if this situation possible? And if it is, is there a way to make the release/nil atomic?
this is actually not entirely correct
[self.obj release]
self.obj = nil;
you should write simply
self.obj = nil;
which will call the setter that will release the previous instance.
Yes, it could blow up. Consider your code example.
[self.obj release];
self.obj = nil;
You use self.obj which means you are referencing accessor/mutators methods instead of accessing your object directly. Chances are you'd declare "obj" as a retained property. Your .h would be something like...
#property (retain) Something *obj;
and your .m
#synthesize obj;
If you later release your object by using the methods created by your #synthesize you are safe.
[self setObj:nil];
// or equally valid
self.obj = nil;
// Below is (almost) identical way to access, release and nil the variable directly.
// The major difference is you don't multi-threaded protection of your property
// declaration (explained below).
[obj release];
obj = nil;
If you look back at the property I specified above you'll notice I didn't put in the very commonly seen nonatomic. It wasn't by accident. Take a look at Apple's docs
Properties are atomic by default so that synthesized accessors provide robust access to properties in a multithreaded environment—that is, the value returned from the getter or set via the setter is always fully retrieved or set regardless of what other threads are executing concurrently.
You can surround both operations in an #synchronized block to ensure that both operations complete before leaving the block:
#synchronized(lockObject)
{
[self.obj release];
self.obj = nil;
}
Provided that any other threads that might access that variable also synchronize around the same lock object, you shouldn't run into any issues.

Singleton again, but with multi-thread and Objective-C

I know Singleton pattern has been discussed so much. But because I'm not fully understand the memory management mechanism in Objective-C, so when I combined Singleton implementation with multithreading, I got a big error and cost me a whole day to resolve it.
I had a singleton object, let's call it ObjectX. I declared an object inside ObjectX that will detach a new thread, let's call that object objectWillSpawnNewThread, when I called
[[ObjectX sharedInstance].objectWillSpawnNewThread startNewThread];
The new thread could not be executed correctly, and finally I found out that I should not declare the object objectWillSpawnNewThread inside the singleton class.
Here are my questions:
How does Objective-C allocate static object in the memory? Where does Objective-C allocate them(Main thread stack or somewhere else)?
Why would it be failed if we spawn a new thread inside the singleton object?
I had searched the Objective-C language [ObjC.pdf] and Objective-C memory management document, maybe I missed something, but I currently I could not find any helpful information.
Learn the memory management rules. They are simple and in a week you’ll have the time investment back.
Forget about singletons. More precisely, forget about singletons enforced by code. They are unnecessarily complicated and 99% of the time are simply bad design.
Read Singletons are Pathological Liars by Miško Hevery, read it carefully, read all of the related blog posts and think about it. Most of the time there is no real need for a class to enforce having a single instance. Usually you can get around the problem by creating some kind of Factory class that will create most instances for you and wire them together:
#interface Factory {
id classYouWantJustOneInstanceOf;
}
- (id) wireMainController;
#implementation Factory
- (id) init {
[super init];
// No “sharedFoo” stuff necessary. Foo is a plain
// class without singleton boilerplate, easily testable.
classYouWantJustOneInstanceOf = [[Foo alloc] init];
return self;
}
- (id) wireMainController {
id controller = [[SomeClass alloc] init];
// Dependencies set explicitly, good.
[controller setFoo:classYouWantJustOneInstanceOf];
return [controller autorelease];
}
#implementation UIApplicationDelegate
- (void) applicationDidFinishLauching: (UIApplication) app {
// Now all your “singletons” will get created,
// no funny static stuff.
factory = [[Factory alloc] init];
controller = [[factory wireMainController] retain];
[window addSubview:controller.view];
// up and running
}
- (void) dealloc {
[controller release];
// Now all your “singletons” will get released.
[factory release];
[super dealloc];
}
I know this feels a bit uneasy compared to “simple” [Foo sharedFoo], but it’s worth it, trust me.
The advantages of this solution, in case they are not apparent:
No singleton boilerplate in your classes. No static shared instances, no thread synchronization, nothing.
Explicit dependency management. If class A needs instance of B to do its work, you can see that from a public setter or a constructor parameter of A. No suprise dependencies inside the implementation file. And if you need to wire A differently, say for testing purposes, it’s easier when the dependencies are explicit (as opposed to calling [B sharedB]).
Clear object lifecycle. No static variables, no static initialization and no lazy initialization unless you really want it. You know when objects get created and you can deallocate everything you create.
Note that this is a simplified case, so that the division between application delegate and Factory seems a bit pedantic, but in a real case it makes perfect sense (see the Principle of single responsibility).
It's hard to say what you did wrong unless you post some code, but there's no magic involved with singleton objects. There is no suuch thing as a static object.
Question 1:
All Objective-C objects are allocated from the heap. You can declare pointers to them from any scope, but somewhere in your code, directly or indirectly, the object's class must be sent the alloc message and the resulting pointer initialised and assigned to your pointer. Your object's instance variables must be initialised in your object's init method. So one way to implement your singleton would be as follows:
// Header
#interface ObjectX : NSObject
{
SpawnObject* objectWillSpawnNewThread;
}
+(ObjectX*) sharedInstance;
// Implementation
#implementation ObjectX
-(id) init
{
self = [super init];
if (self != nil)
{
objectWillSpawnNewThread = [[SpawnObject alloc] init];
}
return self;
}
+(ObjectX*) sharedInstance
{
static ObjectX* sharedInstance;
#synchronized([ObjectX class])
{
if (sharedInstance == nil)
{
sharedInstance = [[ObjectX alloc] init];
}
}
return sharedInstance;
}
#end
Question 2:
Can't tell you the answer, unless you post your code and the error message. However, one common problem is forgetting to set up an autorelease pool inside the new thread.