2

The normal way to initialise and allocate in Objective-C is

NSObject *someObject = [[NSObject alloc] init];

Why is the following not practised?

NSObject *someObject = [NSObject alloc];
[someObject init];
jscs
  • 63,694
  • 13
  • 151
  • 195
  • 4
    im guessing because you cant do anything useful with an un-inited object, so why separate the calls out? as an alternative you can just go `[NSObject new];` which is a convenience method for allocing and initing – Fonix Feb 16 '15 at 09:07

4 Answers4

10

The main problem is that you might end up using the wrong object.

init is special in many classes as it might just release the receiver and instead create a new object that resides at a different address. So your someObject then points to the wrong (uninitialized) instance.

There are a lot of framework classes that use the arguments of the init method to decide which kind of specialized subclass is best to use. This frequently happens with class clusters like NSString or NSArray but it can really happen with each kind of object.

One place where you can see this special behavior of initializers is ARC: It explicitly declares that the init family of methods eats up the receiver and returns a +1 retained object. This would not be necessary if initializers would just always return the receiver.

Of course you could fix your code by just doing another assignment:

NSObject *someObject = [NSObject alloc];
someObject = [someObject init];

This would fix the problem. But there's also no sense in doing it.

Nikolai Ruhe
  • 81,520
  • 17
  • 180
  • 200
4

From the Object Initialization official documentation:

Because an init... method might return nil or an object other than the one explicitly allocated, it is dangerous to use the instance returned by alloc or allocWithZone: instead of the one returned by the initializer

Another reason from the same document is that:

Once an object is initialized, you should not initialize it again

given this example:

NSString *aStr = [[NSString alloc] initWithString:@"Foo"];
aStr = [aStr initWithString:@"Bar"];

where:

the second initialization in this example would result in NSInvalidArgumentException being raised.

tkanzakic
  • 5,499
  • 16
  • 34
  • 41
1

Because it is less simple and more error-prone.

An allocated but not initialised object is useless, so it make sense to put allocation and initialisation in one line. If they are separated, there is more possibility for errors and bugs if the two lines are not directly after each other (perhaps after refactoring), which may lead to errors while trying to use an uninitialised object.

There simply isn't a single good reason to alloc and init in separate lines, and many reasons against it.

p4sh4
  • 3,292
  • 1
  • 20
  • 33
0

As per my understanding an allocated object makes no sense without it being initialized,

if you alloc an object first and then later plan to initialize it, there might be a case that you may forget to initialize the object and give a direct call to any of its instance method which would result in run time error.

Example:

    NSString *str = [NSString alloc];
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
NSLog(@"%ld",str.length);

When i run the above code i get this in my console

Did you forget to nest alloc and init?
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '*** -length only defined for abstract class.  Define -[NSPlaceholderString length]!'

if i would do the below I would still get the exception as str is not being initialized because whatever is being initialized is not being consumed or pointed by str

[str init];

Hence if you want to do it in two lines it should be like this

NSObject *someObject = [NSObject alloc];
someObject = [someObject init];

But it's always better to keep them nested

NSObject *someObject = [[NSObject alloc]init];

If you plan on doing it on single line then use the new keyword which servers the purpose of allocation and initialization on a single line.

Example: YourClass *object_ofClass = [YourClass new];

Bug Hunter Zoro
  • 1,743
  • 18
  • 21
  • 1
    In your example the problem is not the omission of the init. You can insert a line `[myDict init];` before the `NSLog` and still get the same exception. The error stems from the object returned from `alloc`. It is a plain `NSDictionary` which is never actually used in the class cluster. – Nikolai Ruhe Feb 16 '15 at 10:14