Should I always release self for failed init methods? - objective-c

Should I always release self when there is a failure inside init, or should I only do so if I have initialized instance variables first?
To put it another way, is this pattern valid? Is there a time when I shouldn't release self inside an init method, or should I assume that if the control flow enters init, self has at least a retain count of 1?
- (id)init
{
if ((self = [super init]) == nil)
{
[self release];
return nil;
}
//do some init stuff
if (somethingFailed)
{
[self release];
return nil;
}
return self;
}

If some check you need in your initialization method fails, then yes you should release self. Note however, that if [super init] returns nil it does not make sense to send release to self as self is nil. This is actually frowned on by Apple:
You should only call [self release] at the point of failure. If you get nil back from an invocation of the superclass’s initializer, you should not also call release.
Example:
- (id)init
{
self = [super init];
if(self) {
// do some init stuff
if (somethingFailed)
{
[self release]
self = nil;
}
}
return self;
}
Also see the Mac Dev Center documentation on Handling Initialization Failure

Related

Creating a local singleton correctly Obj C. (Not a shared global Singleton)

I'm designing a class that MUST only have one instance of itself at any time. I'm trying to avoid the common pattern of a shared singleton that is globally accessible, I only want a local object that can only be allocated once but can also be set to nil. How does this look?
static BOOL isInitialized = NO;
#implementation Single
-(instancetype) init
{
if (isInitialized == NO)
{
if (self = [super init])
{
}
isInitialized = YES;
return self;
}
else
{
NSAssert(FALSE, #"Only one instance allowed");
return nil;
}
}
-(void) dealloc
{
isInitialized = NO;
}
#end
I'm not concerned about thread safety as I only plan to use class on main thread. When the object is deferrenced the overridden dealloc should ensure a new instance can be created. Anybody see any issues with this or improvements? Cheers
It's a corner case, but as written if the call to [super init] fails then isInitialized will be set to YES (Note that in this case the passed in self is deallocated before the flag is set) - this means that no instance of the class will ever be created as there is nothing to deallocate to reset your flag. Maybe you want:
if (self = [super init])
{
isInitialized = YES;
}
return self;
Otherwise, given that you are not concerned over thread safety and you want a second allocation attempt to be a failure (your use of NSAssert), your code looks fine.
Would it be better to return the existing instance instead of crashing?
#implementation Single
- (instancetype)init {
static __weak Single *weakInstance;
Single *strongInstance = weakInstance;
if (strongInstance) {
self = strongInstance;
} else {
if (self = [super init]) {
weakInstance = self;
}
}
return self;
}
You don't need to do anything special in dealloc because the system will clear the __weak reference automatically when the instance is deallocated.
#Rob
Can the strong reference be removed from your method?
- (instancetype)init
{
static __weak id weakInstance;
if (weakInstance)
{
self = weakInstance;
}
else
{
if (self = [super init])
{
weakInstance = self;
}
}
return self;
}
seems to work.

Followup to returning nil from a [[class alloc] init]

As follow-up of sorts to Is returning nil from a [[class alloc] init] considered good practice?, there's a case that I haven't seen any discussed much: what to do with an init that fails some preconditions before it can call the next init?
Example, suppose in this initWithStuff: method being passed nil or in general having no value to pass to initWithValue: is an absolute failure and we definitely want to return nil.
- (id)initWithStuff:(Stuff *)inStuff {
if (!inStuff || ![inStuff hasValidValue])
{
// can't proceed to call initWithValue: because we have no value
// so do what?
return nil;
}
NSInteger value = [inStuff integerValue];
return [super initWithValue:value];
}
Perhaps a clearer example is if the designated initializer method we wrap takes an object pointer and throws an exception if its passed nil. We definitely need to short-circuit that init call that would cause an exception.
My guess: init by any means possible, and only then release self before returning nil. If necessary, call bare init or any other initializer that will work to finish putting self into a known state before releasing it.
// can't proceed to call super's initWithValue: because we have no value
// so do what? do this:
self = [super init]; // or initWithValue:0
[self release];
return nil;
And if there were no such initializer that will work without valid data, I guess one would need to construct some valid, dummy data. Or complain to its author and until then just return nil and live with the leak :^)
Also, how does ARC affect the situation?
My guess: still finish init by any means possible, then just return nil. You'd think setting self might be redundant, but in some cases it's not. In any case, it but it needs to be there to silence a compiler warning.
// can't proceed to call super's initWithValue: because we have no value
// so do what? do this:
self = [super init]; // finish init so ARC can release it having no strong references
return nil;
Are my guesses wrong in any way?
Ideally, if a precondition fails, you don't call [super init…]. You just release self (if not using ARC) and return nil:
- (id)initWithStuff:(Stuff *)stuff {
if (!stuff || ![stuff isValid]) {
[self release]; // if not using ARC
return nil;
}
if (self = [super init]) {
// initialization here
}
return self;
}
The release takes care of deallocating self under MRC. Under ARC, the compiler will insert the release for you.
However, there is a potential problem with this approach. When you release self (or when ARC releases it for you), the system will send the dealloc message to the object. And your dealloc method will call [super dealloc]. You could suppress the [super dealloc] under MRC, but you can't avoid it with ARC.
So the danger is that your superclass might assume that one of its instance variables has been initialized, and rely on that initialized value in its dealloc. For example, suppose this is the superclass:
#interface SomeSuperclass : NSObject
#end
#implementation SomeSuperclass {
CFMutableBagRef bag;
}
- (id)init {
if (self = [super init]) {
bag = CFBagCreateMutable(NULL, 0, &kCFTypeBagCallBacks);
}
return self;
}
- (void)dealloc {
CFRelease(bag);
}
#end
The problem here is that CFRelease requires its argument to not be nil. So this will crash during deallocation if you don't call [super init] in your subclass.
Given this problem, I have to change my initial recommendation. If you know that your superclass's dealloc doesn't have this sort of problem (because, for example, it checks pointers before dereferencing them or passing them to CFRelease), then you can safely not call [super init].
If you don't know that your superclass's dealloc is safe, then my recommendation is that you move your preconditions out of init and into a class factory method.
In other words, don't treat alloc/init as part of your class's public interface. Provide a class method for creating instances:
// The class factory method. Declare this in your header file. This is how you
// or any user of this class should create instances.
+ (id)myObjectWithStuff:(Stuff *)stuff {
if (!stuff || ![stuff isValid])
return nil;
// self here is the class object, so it's appropriate to send `alloc` to it.
// You don't want to hardcode the class name here because that would break
// subclassing.
return [[self alloc] initWithStuff:stuff];
}
// This is now considered a private method. You should not declare it in your
// header file, though in Objective-C you can't prevent the user from calling it
// if he's determined to.
- (id)initWithStuff:(Stuff *)stuff {
// Precondition was already checked in myObjectWithStuff:.
if (self = [super init]) {
// initialization here...
}
return self;
}

in objective-c, is if(self) { [self initFOO] } redundant?

I am studying from the Stanford CS193P from Paul Hegarty. Then I see something like this, which I also see other people using:
- (id)init
{
self = [super init];
if (self) {
[self someSetupFunctions];
}
return self;
}
Isn't that redundant? Why not just use:
- (id)init
{
self = [super init];
[self someSetupFunctions];
return self;
}
I thought that messages to nil just fizzle, so why not use this second format?
You may want to do other things than passing messages to self. For example:
- (id)init
{
self = [super init];
if (self) {
// set up ivars
_anIvar = 5;
}
return self;
}
What's really meant by [self someSetupFunctions] is some initialization code, not just a single method call, and a number of important things will fail if self is nil. Most notably, attempting to assign initial values to instance variables will crash.
The self = [super init]; if (self) test is because some initialisers will return different objects, including nil if it's impossible to create an object that satisfies the condition required by the initialiser.
In your own initialiser you need to defend against the superclass doing that, because if you try to access an instance variable on nil you're definitely doing the wrong thing (whether it crashes as a result or not: it usually will).

Is this valid code to create a NIB-instantiated singleton?

Assume that I instantiate an object of class MyGreatClass in my NIB (as usual by simply dragging an "Object" to the NIB and settings its class to MyGreatClass).
I want access to that instance anywhere in my codebase, without introducing coupling, i.e. without passing objects around like crazy, and without having an outlet to it in, say, [NSApp delegate]. (The latter would make AppDelegate terribly bulky with time.)
I ask: Is the following considered a good code to accomplish this?
//imports
static MyGreatClass *theInstance = nil;
#implementation MyGreatClass
+ (MyGreatClass *)sharedInstance
{
NSAssert(theInstance != nil, #"instance should have been loaded from NIB");
return theInstance;
}
- (id)init //waking up from NIB will call this
{
if (!theInstance)
theInstance = self;
return theInstance;
}
// ...
If this work as expected, I would after the app is loaded be able to access my instance via sharedInstance.
What do you think?
UPDATE: Hmm, on the second thought, the above init method maybe overkill. This is way simpler to think about:
- (id)init
{
NSAssert(!theInstance, #"instance shouldn't exist yet because only "
#"the NIB-awaking process should call this method");
theInstance = self;
return theInstance;
}
Again, what do you think?
The proper way to create a singleton is to override allocWithZone: to ensure another object cannot be created. Overriding init allows the new object to be created, but not initialized. It is thrown away because the init method simply ignores it and returns the object that has been created already. Here is how I would do it:
+ (MyGreatClass *)sharedInstance {
NSAssert(theInstance != nil, #"instance should have been created from NIB");
return theInstance;
}
+ (MyGreatClass *)allocWithZone:(NSZone *)zone {
if(theInstance) return theInstance;
return [[self alloc] init];
}
- (id)init {
if(theInstance) return theInstance;
if(self = [super init]) {
theInstance = self;
// other initialization
}
return self;
}
- (void)release {}
- (void)dealloc {
return;
[super dealloc]; // Prevent compiler from issuing warning for not calling super
}
I overrode release and dealloc to ensure that the singleton would not be deallocated. If you don't do this, you should retain and autorelease it in the sharedInstance method. If you want to support multithreading, you should also synchronize access to the theInstance variable.

Doesn't the standard object initialization in Objective-C lead to memory leaks?

The standard way to create an object in Objective-C looks like this:
MyClass* object = [[MyClass alloc] init];
The standard implementation of MyClass's init method would look something like this:
-(id) init
{
self = [super init];
if(self) { /* initialize */ }
return self;
}
Aside from some syntax changes, and excluding factory methods, that seems to be the recommended way to write an init method, and to use it.
As I understand it, the purpose of self = [super init]; is to handle the case where [super init] fails. But if it does fail, and returns nil, wouldn't there be a memory leak? The reason being that MyClass's init will return nil, object will be nil, there will be no more pointers that reference the object allocated with [MyClass alloc], and therefore no way to release it.
These are the two solutions I can think of are, but I haven't seen either one in regular practice.
After a call to alloc, check the results before calling init:
MyClass* object = [MyClass alloc];
if(object == nil) { /*handle the error */ }
else { object = [object init]; }
Or, if [super init] fails, release the memory. Something like this:
-(id) init
{
id temp = [super init];
if(!temp) { [self release]; }
self = temp;
if(self) { /* initialize */ }
return self;
}
Am I wrong in that reasoning? It could be argued that [super init] is unlikely to fail, but then why assign the results of it to self and check for nil? I'd be happy to see some clarification.
If [super init] wants to return nil, it should also call release on self.
An init method should get rid of the object if it decides to abort and return nil.
However, that's just what the if (self) covers. The self = [super init] serves another purpose: An init method is allowed to return something other than the object that the message was sent to. For a real-life example, [NSArray alloc] returns a dummy object, and that object's various init… methods return the real array.