0
+ (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 ??

4
  • The first one does also the alloc part... And not that it has a "+" and not a "-". Commented Mar 13, 2013 at 10:13
  • Note that you normally return autoreleased object from class-method initializers, that's what everyone would expect from it. Commented Mar 13, 2013 at 10:18
  • Is returning an auto-released object still relevant with ARC? Commented Mar 13, 2013 at 10:20
  • I don't believe it is. Commented Mar 13, 2013 at 10:23

2 Answers 2

6

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 return autoreleased references:

+ (id)packetWithType:(PacketType)packetType
{
    return [[[[self class] alloc] initWithType:packetType] autorelease];
}

This is important to know in order to avoid dangling references and/or memory leaks:

Thing* thing = [[Thing alloc] initWithFoo: xyz];
// Now, *I* own the reference and *I* am responsible for releasing
// it, when I no longer need it.
[thing release]

On the other hand, the reference returned by

Thing* thing = [Thing thingWithFoo: xyz];

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 actually retain it here:

self->myMember = [thing retain];

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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:

  1. The object is not yet allocated when they are called so the method can decide which class to allocate. Class clusters might use this to find the proper class depending on the parameters of the constructor.
  2. The method might also decide to return an already existing object from a shared cache.
  3. The return value can be statically typed.

Note that your convenience constructor would typically be:

+ (Packet *)packetWithType:(PacketType)packetType
{
    return [[self alloc] initWithType:packetType];
}

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 use instancetype as the return type.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.