Need to release twice? - objective-c

I can't seem to find the answer anywhere. I'm using Manual Memory Management in Objective-C developing for iOS.
I wrote a convenience function for getting UIColor from a hex string. In it, it returns
[[UIColor alloc] initWithRed:... alpha:alpha]
Apparently on certain platforms (we have a few devices, ranging iOS 8-9) the object would be destroyed on exiting the function, so that its returned UIColor* cannot be used. So now, we changed it to
[[[UIColor alloc] initWithRed:... alpha:alpha] retain]
My question is when I'm done using this object, do I have to release it twice? Once for the alloc, once for the retain? It seems very strange to me, and I can't find this online anywhere.
If I don't retain, it gets dealloc'd on exiting the function (on some platforms) making the function useless. If I do retain, I need to release twice when done?
EDIT:
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html
"..., it is normally guaranteed to remain valid within the method or function it was received in. If you want it to remain valid beyond that scope, you should retain or copy it. "
So I'm not doing anything out of the ordinary. The docs say I "should retain it" if "I want it to remain valid beyond" the scope of a function. I will try what #FreeNickname suggested. That makes the most sense.

You said:
I wrote a convenience function for getting UIColor from a hex string. In it, it returns
[[UIColor alloc] initWithRed:... alpha:alpha]
According to the Basic Memory Management Rules, the proper memory management is dictated by the name of your method:
if your method name does not start with “alloc”, “new”, “copy”, or “mutableCopy”, then you should return an autorelease object:
- (UIColor *)colorWithHexString:(NSString *)hexString {
...
return [[[UIColor alloc] initWithRed:... alpha:alpha] autorelease];
}
if your method name does start with “alloc”, “new”, “copy”, or “mutableCopy”, then you can return an object like you have above:
- (UIColor *)newColorWithHexString:(NSString *)hexString {
...
return [[UIColor alloc] initWithRed:... alpha:alpha];
}
Note, this pattern is less common than the above convention of colorWithHexString.
(Note, this memory management dictated by the method name prefix was historically merely best practice, but now, for interoperability with ARC code, it's critical. Always follow the above rules in manual reference counting code.)
Now, if the code that is calling your convenience initializer is allowing the object to be deallocated, the problem rests with that code, not your convenience initializer. Do not start adding extra retain statements to your initializer because something that calls it doesn't manage its memory properly.
Instead, make sure that the calling code does the proper retain (and eventual release) of the result of colorWithHexString, itself.
By the way, Xcode's static analyzer (shift+command+B) is remarkably good at analyzing manual reference counting code and identifying the issues.
In an edit to your question, you quoted the documentation:
If you receive an object from elsewhere in your program, it is normally guaranteed to remain valid within the method or function it was received in. If you want it to remain valid beyond that scope, you should retain or copy it. If you try to release an object that has already been deallocated, your program crashes.
This is not saying that your convenience initializer should issue a retain or copy. It is saying that the code that calls colorWithHexString is responsible for establishing its own claim of ownership of the UIColor object that was returned via retain or copy, as discussed above.

I think you are looking for the concept of autorelease which is used in situations like yours. It is essentially a way to send a deferred release message to the newly created object so the caller has the chance to retain it if necessary, otherwise it is destroyed when the autoreleasepool is processed.

You "misunderstood" Apple's documentation, because it is simply wrong for this topic. You really should read clang's documentation about ARC instead of Apple's, because clang's ARC documentation explains MRC correctly to interact with it.
Let's have a closer look on it:
You own any object you create by allocating memory for it or copying it.
Related methods: alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone:
…
Conversely, if you are not the creator of an object and have not expressed an ownership interest, you must not release it.
…
If you receive an object from elsewhere in your program, it is normally guaranteed to remain valid within the method or function it was received in.
Taking this documentation for serious, you are not an owner of the object:
[[UIColor alloc] initWithRed:... alpha:alpha]
This is, because you do not receive the object reference from +alloc et al., but from -init…. Following Apple's documentation you are not an owner and have to retain it. (So it is "elsewhere".)
In clang's documentation it is described differently and correctly:
Methods in the init family implicitly consume their self parameter and return a retained object. (5.2.1)
Therefore there is a special method family for -init… along with the others mentioned in Apple's documentation as correctly described in clang's documentation:
The families and their added restrictions are:
alloc methods must return a retainable object pointer type. [Apple: alloc, allocWithZone:)
copy methods must return a retainable object pointer type. [Apple: copy, copyWithZone:)
mutableCopy methods must return a retainable object pointer type.(Apple: mutableCopy, mutableCopyWithZone:)
new methods must return a retainable object pointer type. (Apple: Ooops, I forgot something)
init methods must be instance methods and must return an Objective-C pointer type. … (Apple: Oooops, I forgot something)
(5.)
So, what you get from -init is already retained, you have the ownership and there is definitely no reason to retain it.
According to Rob's answer there might be a reason to autorelease it.

Related

release for objects on Class method?

Without using ARC, for objects initialized using instance method we do release it via release call.
example:
Sample *obj = [[Sample alloc]init] ;
// some code here
[obj release] ;
Now for objects allocated using class methods should release be called?
example:
TestSample *testobj = [TestSample initCustom] ;
// some code here
should there be [testobj release]?
Let's consider this standard function provided by apple.
endpointWithHostname is a class method.
NWHostEndpoint *pNetHost = [NWHostEndpoint endpointWithHostname:#"0.0.0.0" port:#"21"];
so, should there be a [pNetHost release] for above call?
You said:
for objects initialized using instance method we do release it via release call
The fact that you called an instance method isn’t relevant. You own any object returned by any method whose name starts with alloc, new, copy, or mutableCopy. In your example, you called alloc, and therefore ownership has been transferred to you. That’s why you are now responsible for calling release.
However, if you called some instance method that didn’t start with one of those four prefixes, though, ownership would not be transferred to you, and you would not call release.
This is all summarized in the Advance Memory Management Programming Guide, which says:
Basic Memory Management Rules
The memory management model is based on object ownership. Any object may have one or more owners. As long as an object has at least one owner, it continues to exist. If an object has no owners, the runtime system destroys it automatically. To make sure it is clear when you own an object and when you do not, Cocoa sets the following policy:
You own any object you create
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).
You can take ownership of an object using retain
A received object is normally guaranteed to remain valid within the method it was received in, and that method may also safely return the object to its invoker. You use retain in two situations: (1) In the implementation of an accessor method or an init method, to take ownership of an object you want to store as a property value; and (2) To prevent an object from being invalidated as a side-effect of some other operation (as explained in Avoid Causing Deallocation of Objects You’re Using).
When you no longer need it, you must relinquish ownership of an object you own
You relinquish ownership of an object by sending it a release message or an autorelease message. In Cocoa terminology, relinquishing ownership of an object is therefore typically referred to as “releasing” an object.
You must not relinquish ownership of an object you do not own
This is just corollary of the previous policy rules, stated explicitly.
You go on to ask:
let's consider this standard function provided by apple. endpointWithHostname is a class method.
NWHostEndpoint *pNetHost = [NWHostEndpoint endpointWithHostname:#"0.0.0.0" port:#"21"];
so should there be a [pNetHost release] ; for above call
The fact that it is a class method isn’t relevant. The key is that the method name doesn’t start with alloc, new, copy, or mutableCopy. That means that ownership has not been transferred to you and therefore you don’t need to call release. In this case, it is returning an autorelease object, so it will be released for you when the autoreleasepool is drained.
Obviously, if you want to claim ownership of the pNetHost object, you would do so by calling retain (and of course, at that point you’d then be responsible for eventually calling release to offset that retain).
Now, let’s consider your example:
TestSample *testobj = [TestSample initCustom];
// some code here
should there be [testobj release]?
No. But let’s answer this question by looking at the implementation of the method you called initCustom. It might be implemented like so:
+ (instancetype)testSample {
TestSample *obj = [[self alloc] init];
// perhaps more customization of `obj` here
return [obj autorelease];
}
But, there are two key observations in the above:
I didn’t start the method name with init. That prefix should only be used with initialization methods, which this method isn’t.
The convention is to start the method name with the name of the object type, using camelCase (i.e. starting with a lowercase letter). Hence, this TestSample class method name might be called testSample, like above, not initCustom.
Because the method name doesn’t start with alloc, new, copy, or mutableCopy, it should return an autorelease object. And because it is an autorelease object, the caller would therefore would not call release (unless, of course, it claimed ownership by calling retain).
By the way, the static analyzer (shift+command+B; or “Product” » “Analyze”) is exceptionally good at analyzing manual reference counting code.
For example, let’s imagine that I forgot to add the autorelease in the above testSample example. If I let Xcode analyze the code, the compiler would tell me about the problem:
If I add the autorelease back in and re-analyze, this warning will go away.
When writing manual reference counting code, the static analyzer is an invaluable tool. Always make sure you have a clean bill of health from the analyzer.

__bridge_transfer and performSelector:withObject:

I have a CFDictionaryRef that doesn't retain/release its objects. When I add an item in it, I take care of retaining it, and later :
NSMutableArray *array = (__bridge_transfer NSMutableArray *)CFDictionaryGetValue(...)
[self performSelector:someSelector withObject:array];
Where someSelector is a variable holding a selector I know about. Now, that second line makes Xcode tell the notorious warning:
PerformSelector may cause a leak because its selector is unknown
Does that mean I should worry about ARC not knowing how to manage memory for the array variable of which I just transferred ownership?
From a comment to the accepted answer of this question, it appears that somebody at Apple has confirmed this hypothesis (citing the answer itself):
In fact, there are times when memory management is tied to the name of the method by a specific convention. Specifically, I am thinking of convenience constructors versus make methods; the former return by convention an autoreleased object; the latter a retained object. The convention is based on the names of the selector, so if the compiler does not know the selector, then it cannot enforce the proper memory management rule.
Thus, it has nothing to do with a possible leak of arguments passed to the performSelector: call, but rather to its returned value, for which Objective-C has no way of knowing if it was autoreleased or not. This is also what Martin R from the comments was assuming.

What method families exist in objective-c/cocoa for iOS?

I am a experienced developer that is new to iOS developement (on iPhone in particular). A project I am working on is using Automatic Reference Counting (ARC).
I was doing some research on ARC and came across this document: http://clang.llvm.org/docs/AutomaticReferenceCounting.html and in a section titled: "Retained return values" it states that an attribute can be used to indicate that the caller expects to take ownership of a +1 retain count. It also goes on to state that ARC will automatically add the attribute to methods if it detects it is in particular method families (it specifically names: alloc, copy, init, mutableCopy, and new)
From further reading it seems that method families are simply method naming conventions. My understanding is that if the method name starts with a method family then it is in that method family. So for example
+(id) init
+(id) initWithName:(NSString*)name
are both part of the init method family.
My question is: Is there a formal list of defined Method Families for iOS development and if so, what are they / where might I find it?
below is the section llvm.org I mentioned above:
Section 3.2.2: Retained return values states:
A function or method which returns a retainable object pointer type
may be marked as returning a retained value, signifying that the
caller expects to take ownership of a +1 retain count. This is done by
adding the ns_returns_retained attribute to the function or method
declaration, like so:
id foo(void) __attribute((ns_returns_retained));
- (id) foo __attribute((ns_returns_retained)); This attribute is part of the type of the function or method.
When returning from such a function or method, ARC retains the value
at the point of evaluation of the return statement, before leaving all
local scopes.
When receiving a return result from such a function or method, ARC
releases the value at the end of the full-expression it is contained
within, subject to the usual optimizations for local values.
Rationale: this formalizes direct transfers of ownership from a callee
to a caller. The most common scenario this models is the retained
return from init, alloc, new, and copy methods, but there are other
cases in the frameworks. After optimization there are typically no
extra retains and releases required.
Methods in the alloc, copy, init, mutableCopy, and new families are
implicitly marked attribute((ns_returns_retained)). This may be
suppressed by explicitly marking the method
attribute((ns_returns_not_retained)).
It is undefined behavior if the method to which an Objective-C message
send statically resolves has different retain semantics on its result
from the method it dynamically resolves to. It is undefined behavior
if a block or function call is made through a static type with
different retain semantics on its result from the implementation of
the called block or function.
Rationale: Mismatches with returned results will cause over-retains or
over-releases, depending on the direction. Again, the rule about
function calls is really just an application of the existing C/C++
rule about calling functions through an incompatible function type.
Section 5 of the same document is titled "Method Families". It lists all the currently defined families, which are the ones you identified above; alloc, new, copy, mutableCopy, and init. It also lists the criteria for being part of that family. Mostly, it's just based on the method name, but it also depends on the return type. For example, a member of the copy family must return an object; a copy method that has a void return type will not be considered part of the copy method family.
I don't know that I've seen a formal list of method families, but your analysis is basically correct. I believe the only method naming conventions that have compiler-enforced semantics are those mentioned in your post, namely alloc, init, copy (and mutableCopy), and new. Even before/without ARC, the clang static analyzer included in Xcode uses those naming conventions to find memory management problems, and they're also the basis of the longstanding memory management rules for Objective-C programmers prior to ARC.
Namely, if you create an object using a method that begins with init, copy, mutableCopy or new, you "own" that object and are responsible for releasing it later. Objects created or returned by methods with any other name, are not owned by you, the caller, and if you want to keep a reference to them, you must retain them. Every retain you make must be balanced by a later release, when you're done with the object reference. Finally, calling autorelease on an object puts it in the innermost autorelease pool. The pool is responsible for releasing the object later, where later is sometime after the current scope. So, release and autorelease are both valid ways of relinquishing your retain on an object.
Now, the rules I've set forth shouldn't (and can't) be followed by you, the programmer, under ARC. However, ARC is essentially a system whereby the compiler with help from the static analyzer knows these rules and inserts the necessary memory management calls for you at compile time. So, if you're looking to develop an understanding of what ARC is doing behind-the-scenes, understanding these rules is a good start.
This turned out a bit longwinded, but the point is that the methods you've named are the only ones I know of that have this enforced naming convention in Objective-C, and it stems from the memory management rules set forth above. There are other naming conventions in Objective-C, to be sure, but they're standard style conventions, not something that's enforced anywhere.
Look at official Apple Developer documentation about Memory Management Rules. Seems, your list is complete: “alloc”, “new”, “copy”, or “mutableCopy” (only 4 keywords).
I would include the convenience constructors provided by some Cocoa classes:
- +stringWith* // Various ways to make NSString objects
- +arrayWith*, +dictionaryWith*, etc. // Make collections
- +dateWith* // Make NSDate objects
- etc. // Many, many others
They all return a new, autoreleased instance of the class they are sent to - except for some special cases, see for instance #Peter Hosey's comment.
I don't know if there are any formal rules, but the pattern is that the constructor name is composed of the class name without the NS part (and without the Mutable part, too, for mutable classes) followed by With<Parameter Type>: and one or more parameters. The name begins with a lower case letter (except the usual suspects, like URLWithString:.)
For instance, the following line provides an autoreleased NSArray instance with a single element:
[NSArray arrayWithObject: #"Test"]
I don't know if there are any special rules in the compiler to recognize this type of constructor.

why [self.property release] will cause the static analyzer to show an "incorrect decrement of the reference count" error? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Incorrect decrement of the reference count of an object that is not owned at this point by the caller
Why shouldn't I use the getter to release a property in objective-c?
So, I get that using [self.myProperty release] is discouraged (Apple itself recommends not to). Although it appears to me that it COULD lead to problems in some cases, not all cases. Is this correct? More importantly: I don't get why using a syntax like [self.myProperty release] in my -dealloc method(s) will cause the static analyzer to show an "incorrect decrement" error. Despite any other reason discouraging such a syntax, my class still owns its properties (which I have declared with "nonatomic,retain") so why the warning?
I've been reading several posts on this but it seems I can't really wrap my mind around it.
Some of them go into details about the possible side effects of using such a syntax, but what I really want to know is the reason behind the "incorrect decrement" error.
Any help would greatly be appreciated.
Cocoa memory management has a concept of "ownership" which is expressed most succinctly in the rule: If you call new or alloc, or send retain or copy to an object, you own the result, and are responsible for sending release when you're done with it. Otherwise, you do not own it, and you must not send release.
Instance variables, basically by definition, contain objects that the instance owns. You need the objects to be valid for the life of the instance, so you create them with an ownership-granting method in init:
// myDinkus and creationDate are ivars of whatever class this is.
// They are assigned to with owned references.
myDinkus = [[Dinkus alloc] init]; // ownership due to alloc
creationDate = [[NSDate date] retain]; // ownership due to retain
These now need to be sent release when the instance is done with them; generally speaking, this will be in dealloc.
Getter methods don't return owning references. This is the way it should be; when your code, e.g., asks a label for its font color, it doesn't need that color object to stick around. Or if it does, it must explicitly take ownership by sending retain. Giving it ownership by default would create headaches at best and possibly leaks.
That established, [self.myProperty release] causes the static analyzer to complain because it's a violation of the ownership concept. The object returned from [self myProperty] isn't owned by the caller. The fact that it just so happens to be the same object as an ivar that is owned by the caller is irrelevant. (In fact, it might not be the same; the getter might return a copy of the object it represents, for example. It might construct an entirely new value based on a group of ivars. It's even possible for there to be no ivar that corresponds to a getter.)
Since objects which are not owned must not be sent release, doing so to the result of a getter is incorrect.
There are other, practical, reasons not to do this (covered quite well, especially by Justin's answer in the question proposed as dupe), but that's the reason the analyzer is complaining.
Fundamentally, you're sending a release message to an object that you haven't sent a retain to (at least not explicitly). The static analyzer will expect to see balanced retain/releases.
When you declare your property as nonatomic,retain you are handing responsibility for releasing the value to the property's setter.
If you do a [self.myProperty release] then your property still contains its old value and any subsequent setting of that property will do a release on that old value - but you've already released it, so now it is over-released... Hence the warning.
To release the value you should use self.myProperty = nil - the setter will release the old value and assign nil to the property.

using alloc and init

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.html
Allocating 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];
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html
The init method doesn't receive the object; the object receives the init message. The object does not possess itself; rather, it always knows about itself (through the implicit self argument in every message).
You're right that the object does not own itself, though. If alloc and init were fused in a single new method, 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, and init is not the caller of alloc, 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 nil or 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.
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.
As init releases 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 that init creates or retrieves for it.
As a corollary to this, if init retrieves a previously existing object, it must retain that, so that the caller will own it.
Again examining the hypothetical* new method, it would also need to both release the old object and create (owningly) or retain the substitute.
In all of these cases, it's init acting on behalf of its caller. It's normally dodgy for one method to do another's memory management, but for these cases, init doing it on behalf of its caller is necessary.
*The new method does exist, but simply sends alloc and init, so there's no need to implement it separately.
If initialization fails for some reason and must return null, then you must release the object in order to avoid leaking memory.
Similarly, init may decide to swap in a different object and return it - in that case you must also release the object in order to avoid leaking memory.
In both cases it's necessary because the original object isn't being returned by init, and will be orphaned after the method returns. Alloc has automatically retained the object, so if you don't release it its retain count will be stuck at 1 forever.
[Would another perspective help?]
The init method (and its siblings initWith... and similar) is a bit of an odd case but is not a special case of memory allocation rules. Init is odd because it has a name that sounds like it is going to change the internals of the instance but in fact it may do more than that (it may substitute some other object and initialize that object, for example). The tip-off is in the declaration of init:
- (id) init // the way it is
vs
- (void) init // in some other universe
The init method returns an object, so it might have been better named something like 'return an object that is (class-wise) an equivalent object and that has been initialized'. Most methods do not perform this kind of switcheroo, which makes init a bit different/odd.
There is nothing 'magic' about the alloc / init nesting -- it's just the simplest way to handle the fact that the object that you get back from alloc may not be the same object you get back from init. This works perfectly fine:
NSSomeClass* s = [NSSomeClass alloc];
s = [s init]; // that 's =' part is really important ;-)
and is exactly equivalent to the 'standard' idiom:
NSSomeClass* s = [[NSSomeClass alloc] init];
This is potentially problematic:
NSSomeClass* s = [NSSomeClass alloc]
[s init]; // bad! you ignored the result of init
The implementation of an init method must be done particularly carefully when the implementation returns a different object than the one it receives as the incoming 'self'. In such a case the init method takes on the responsibility of memory management of the 'self' object (because it's not going to return that object - so who else could be expected to do the management?)
It's possible to do some pretty ugly trickery, BTW. Don't try this at home!
// don't do this!
S* s = [S alloc]
[s retain]; // needs to survive 2 init's
S* ss = [s init......]; // s.retain goes 2-->1
S* sss = [s init.....]; // ... goes 1-->0;
Doing this is extremely poor practice because it depends on the init..... method always returning a new object (instead of the one it receives). That's an obviously bad assumption!
NOTE that by "a method receiving an object in 'self'" I mean that the method was invoked upon/by an object, and that object is made available by convention through the 'self' pointer.
The fundamental rule just doesn't apply in this special situation.
In fact, don't worry about it - unless you plan to do Posing, you won't need to write code that does this, and it will have no impact at all on the code you write.
You should continue to follow the fundamental rule in all your code.
And thirdly, the code is more what you'd call "guidelines" than actual rules.
(Captain Barbosa)
alloc/init is a bit of a special case. You have to do the retain/release stuff inside init in such a way that whatever object the caller gets back is owned by the caller and there are no leaks.