6
votes

There are two choices for constructors in Objective C/Cocoa:

1. Class Constructor

Product *product = [Product productWithIdentifier:@"Chocolate"];
// Use product

2. Alloc/init Constructor

Product *product = [[Product alloc] initWithIdentifier:@"Chocolate"];
// Use product
[product release];

What I do

  • I tend to use the class method just because it looks cleaner and you don't need a release.
  • I see a lot of alloc/init - what's the advantage to doing it this way?

My Question

  • Which one is preferable? Or is it just a matter of taste?

Code

For context, the class Product would have the following:

+(Product *)productWithIdentifier:(NSString *)identifier_ {
   return [[[[self class] alloc] initWithIdentifier:identifier] autorelease];
}

-(Product *)initWithIndentifier:(NSString *)identifier_ {
   self = [super init]
   if (self) {
       identifier = identifier_;
   }
   return self;
}
2

2 Answers

5
votes

IMO, the biggest difference between the two approaches comes from the fact that using a "class constructor" you get an autoreleased object; this is the most convenient option when you:

  1. assign the allocated object to a retain properties;

  2. when you create "temporary" objects (think of the various NSString methods that build a string from another string: in many case it happens you need to "chain" such calls; the constructor allows you to "forget" about memory management);

  3. when you add the object to some object that retains it (think: addSubview)

In such cases the syntactical advantage of "class constructor" is foremost, but I think it also makes your code "safer" in terms of memory management.

On the other hand, when you create an object to assign it to an assign property (or directly to an ivar for which you have no property), then alloc/init will do perfectly and be preferable to the "constructor" (IMO).

So, in the end, it depends on the way you are going to use the objects you allocate. The class constructor is a convenience method.

5
votes

If you're using ARC, there's not that much of a difference between the two. If you're not using ARC, the difference is extremely important.

The alloc/init combination gives you an owning reference. That means you must release it later on. The classnameWithFoo variant returns a non-owning reference. You may not release it.

This follows the usual Cocoa naming conventions. All methods return non-owning (autoreleased) instances, except for the methods that start with alloc, copy, mutableCopy and new. These return owning references that you must release.

Which one to use is mostly a matter of taste. However, if you need temporary objects that you can dispose quickly the alloc variant results in slightly fewer method calls (the autorelease) and in a loop, it also reduces the maximum memory footprint. However, in most cases this reduced cost is neglectable.