views:

105

answers:

4

I am wondering if [[alloc] init] is just a convention or if separating the two calls has wider use. For instance, I wonder if people ever call [init] (or friends) on an existing object to "re-initialize" it.

+2  A: 

It can do, if memory is highly constrained (as in an iPhone application) you can 'alloc' one (or a few) instances and then reuse them. You need to be careful about leaks though, as objects retained/created in init are often released/freed at the 'free' message.

AlBlue
If you have such a large object that you are tempted to reuse it you must certainly hold onto some big chunk of memory inside the object. In that case I’d rather cache/share this big data item instead of messing with alloc/init.
zoul
The object doesn't have to be large; there can be many of them, too. In fact, the UIKit takes a similar approach for the table view cells, where the same set of (reused) cell instances are used in a table view with different data in them.
AlBlue
I wish people would get off the "memory contsraints on the iPhone" bandwagon. It has as much memory as my previous desktop and almost as much as the mainframe I worked on 15 years ago. I don't remember their manufacturers calling their memory "highly constrained."
iter
@iter: That’s not a fair argument. The amount of memory available for applications is much lower than the installed size, about 30 megabytes on the 128 MB devices. And the amount of data we routinely work with is much higher than on a mainframe 15 years ago, for example an uncompressed RGBA bitmaps are quite a hogs.
zoul
@zoul: I am making no argument. I am sharing my experience and impressions. Scarcity is a mindset. Apple uses the mobile-device-with-resource-constrains as a catch-all justification for features they don't want to implement or give us access to. I understand their angle. It baffles me when independent developers toe the same line.
iter
+4  A: 

By convention, the only use of the init family is when they call each other. For example:

-(id) initWithSomething:(int)something {
  self = [super init];
  // use something
  return self;
}

-(id) init {
  return [self initWithSomething:3];
}

You might pass around a zombie object where init had never been called, but I cannot think of a good reason to do so. If you want to create an object without knowing the type, you pass around a Class.

-(id) makeAnything:(Class)someClass {
  return [[someClass alloc] init];
}

Edit:

alloc guarantees that all members are initialized to zero, and many init methods rely on that. Calling init more than once breaks that contract.

drawnonward
Whilst this answer is correct, it doesn't answer the question asked: specifically, whether it ever makes sense to. Convention may dictate that they are only called from other init methods; but as I note in my answer there are (uncommon) use cases for it, such as the table view cell instance reuse operation.
AlBlue
UITableViewCell has an explicit prepareForReuse method. In general, an explicit method is a better practice than calling init more than once. Many init methods assume that all variables are zero, which alloc guarantees but a second init call cannot.
drawnonward
+3  A: 

Interesting question. Personally I’d think twice before I started messing with this. It seems to be just begging for a new source of bugs while not bringing anything new that you could not obtain in a safer way. Maybe I just don’t understand what’s going on in alloc and init enough to play with those parts, but I’d found that “dumb” code generally makes me happier (KISS).

zoul
+4  A: 

The convention is to never ever re-initialize objects. You can do so on an extremely limited basis in your own classes that subclass NSObject (or defining a new root), but you should never do so with a subclass of any other class from the system frameworks.

If you want to "re-use" instances of a class, then provide methods for re-use beyond the designated initializer. I.e. you could do:

- (void) reset;

Or:

- (void) resetWithNewState: (MyState *) aState;
bbum