+ (id)packetWithType:(PacketType)packetType
{
return [[[self class] alloc] initWithType:packetType];
}
- (id)initWithType:(PacketType)packetType
{
if ((self = [super init]))
{
// code
}
return self;
}
Why do we need first class method, isn't second one just enough for initialization ??
There are two reasons for having convenience constructor class methods. The first one is, that the idiom of
[[Thing alloc] initWithFoo: xyz]
is really common but inconvenient to have to type anywhere. So,[Thing thingWithFoo: xzy]
is a common abbreviation.A deeper reason has to do with reference counting. Methods starting with
init
are supposed to return a reference of the instance, ownership of which is transferred to the caller. Wheras the convenience class methods usually returnautorelease
d references:This is important to know in order to avoid dangling references and/or memory leaks:
On the other hand, the reference returned by
is owned by the "nearest"
NSAutoreleasePool
. The caller is not responsible for releasing it (in fact, that would be wrong!). If the reference is to be kept around, the caller must actuallyretain
it here:You should know about these conventions even when using ARC, as the underlying rules are still in effect, even if (under ARC) it's the compiler, who generates the code to obey them. The
NARC
acronym is a nice way to remember, which method name prefixes come with certain responsibilities. This answer has the details.Convenience constructors have their place in the language for some reasons. Of course using them is usually shorter but there are other advantages as well:
Note that your convenience constructor would typically be:
Now the return type is statically typed and we don't send the (redundant)
class
message to the class object. With recent compiler versions one could useinstancetype
as the return type.