We know about the complete pattern of alloc/init that alloc and init must be combined.
NSObject *myObj = [[NSObject alloc] init];
1- init method receives the object from another source(not from a alloc,new,copy or alike or retained) so according to the fundamental memory management rule its not the owner and it must not release it. However, “Allocating and Initializing Objects / The Returned Object” article says that init could free the receiver.
How could this be possible when its against the fundamental rule?
2- Also, from the same article, init could return another object or nil. So, in this case, when we use the complete pattern of alloc/init, we could not release the object returned by alloc but we could only release the object returned from init and, init releases the object it received from alloc instead of us.
But init is not a alloc,new,copy or alike method so we must not release the object returned from it as it does not give us the ownership of object.
How could we release the object returned from init although this is against the fundamental rule?
3- Or, to adhere to the last paragraph of the same article, must we accept init method as a special case and use alloc/init pattern as an exception to the fundamental rule?
Memory Management Fundamental Rule:
- You only release or autorelease objects you own.
- You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message.
- You use release or autorelease to relinquish ownership of an object. autorelease just means “send a release message in the future” (to understand when this will be, see “Autorelease Pools”).
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.htmlAllocating and Initializing Objects / The Returned Object:
However, in some cases, this responsibility can mean returning a different object than the receiver. For example, if a class keeps a list of named objects, it might provide an initWithName: method to initialize new instances. If there can be no more than one object per name, initWithName: might refuse to assign the same name to two objects. When asked to assign a new instance a name that’s already being used by another object, it might free the newly allocated instance and return the other object—thus ensuring the uniqueness of the name while at the same time providing what was asked for, an instance with the requested name.
In a few cases, it might be impossible for an init… method to do what it’s asked to do. For example, an initFromFile: method might get the data it needs from a file passed as an argument. If the file name it’s passed doesn’t correspond to an actual file, it won’t be able to complete the initialization. In such a case, the init… method could free the receiver and return nil, indicating that the requested object can’t be created.
Because an init… method might return an object other than the newly allocated receiver, or even return nil, it’s important that programs use the value returned by the initialization method, not just that returned by alloc or allocWithZone:. The following code is very dangerous, since it ignores the return of init.
id anObject = [SomeClass alloc]; [anObject init]; [anObject someOtherMessage];Instead, to safely initialize an object, you should combine allocation and initialization messages in one line of code.
id anObject = [[SomeClass alloc] init]; [anObject someOtherMessage];
The
initmethod doesn’t receive the object; the object receives theinitmessage. The object does not possess itself; rather, it always knows about itself (through the implicitselfargument in every message).You’re right that the object does not own itself, though. If
allocandinitwere fused in a singlenewmethod, that method would be its own (super) caller, so it would own the object (until it returns) and so be unquestionably right in releasing it. Since they are separate, andinitis not the caller ofalloc, you’re right that it does not own the object, so you are right to question this practice.This is one of the few cases where it’s OK for one object to release an object (in this case, itself) on behalf of another. The alternative is not to release it, which, if you’re going to either return
nilor throw an exception, will be a leak.In general, anytime you have an object retain or release itself, you should feel dirty. In this specific case, it’s OK, because you are preventing a bug (a leak) rather than probably creating one.
As
initreleases the old object on behalf of its caller, if it creates a new object, it does that on behalf of its caller. The caller does own the substitute object thatinitcreates or retrieves for it.As a corollary to this, if
initretrieves a previously existing object, it must retain that, so that the caller will own it.Again examining the hypothetical*
newmethod, it would also need to both release the old object and create (owningly) or retain the substitute.In all of these cases, it’s
initacting on behalf of its caller. It’s normally dodgy for one method to do another’s memory management, but for these cases,initdoing it on behalf of its caller is necessary.*The
newmethod does exist, but simply sendsallocandinit, so there’s no need to implement it separately.