355

Learning Objective-C and reading sample code, I notice that objects are usually created using this method:

SomeObject *myObject = [[SomeObject alloc] init];

instead of:

SomeObject *myObject = [SomeObject new];

Is there a reason for this, as I have read that they are equivalent?

Qantas 94 Heavy
  • 15,750
  • 31
  • 68
  • 83
willc2
  • 38,991
  • 25
  • 88
  • 99
  • 12
    I didn't even know that was possible! All the material i've read pretends like the new keyword doesn't exist! – Jonathan Apr 06 '09 at 01:17
  • 81
    Actually "new" is not a keyword in Objective-C, but NSObject implements a class method "new" which simply calls "alloc" and "init". – Don McCaughey Apr 06 '09 at 03:35
  • 3
    Jonathan, that's exactly what prompted my question. They may be functionally equivalent but [[alloc] init] is clearly the dominant idiom. – willc2 Apr 06 '09 at 05:45
  • 1
    I think Apple (from what I can remember from one of their iTunes Stanford lectures) just encourages you to use alloc init instead so that you can understand the process of what's happening. They also don't use new a lot in their sample code, so alloc init seems to be just a general good habit that Apple try to promote. – PostCodeism Feb 27 '17 at 20:40

8 Answers8

301

There are a bunch of reasons here: http://macresearch.org/difference-between-alloc-init-and-new

Some selected ones are:

  • new doesn't support custom initializers (like initWithString)
  • alloc-init is more explicit than new

General opinion seems to be that you should use whatever you're comfortable with.

Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
Jeremy Stanley
  • 5,896
  • 1
  • 29
  • 21
  • 5
    That custom initializer thing is a compelling reason to favor [[alloc] init]] over new in my opinion. Thanks for the lightning-quick answer. – willc2 Apr 06 '09 at 05:40
  • 8
    If your class uses -init as the designated initializer, +new will call it. What Jeremy is referring to is if you have a custom initializer that isn't -init. -initWithName:, for example. – bbum Sep 21 '09 at 15:48
  • 88
    There is nothing that stops you from implementing `+newWithString:` as well, if you already implemented `-initWithString`. Not that common though. Personally I always use `new` when the designated initializer is `init`, just soo short and sweet. – PeyloW Sep 21 '09 at 18:38
  • 11
    I know this is an old thread, but I just want to stress that you _shouldn't_ implement `+newWithString:`. That breaks separation of concerns. For when you just want to use `-init` anyway, there's no reason not to just use `+new`, though. – Jonathan Sterling May 25 '12 at 18:05
  • I want to add that implementing a +newWithString: would cause you to create potentially unnecessary properties for values which you could just use ivars for. – SpacyRicochet Oct 10 '13 at 12:39
  • 7
    @JonathanSterling: Apple has many instances where they appear to be doing exactly the thing you advise against; for example `[[NSString alloc] initWithFormat:...]` and `[NSString stringWithFormat:...]` are both equivalent. Are you saying Apple violated separation of concerns and shouldn't have implemented it this way? (Note: I'm not trying to be condescending; I would just like to get more info, and know if following Apple's lead is sometimes a bad idea.) – Senseful Oct 11 '13 at 21:36
  • 2
    Is new() therefore a convenience method, since there is no alloc and init involved? Does it therefore return an auto-released object unlike alloc->init ? – pnizzle Dec 13 '13 at 00:50
  • By "there is no alloc init involved" i mean in the use of new(), I Do know new() simply calls alloc-init (thats why its a convenience method or constructor as some may want to point out) – pnizzle Dec 13 '13 at 01:04
  • 6
    @Senseful I believe that dates back to the days before ARC (or garbage collection). Those two things we're not equivalent. stringWithFormat: would return an autoreleased string while alloc:init: would need to be manually released or autoreleased, or else it would cause a memory leak. – msfeldstein Dec 01 '14 at 19:08
  • 2
    Ok, so it's 2015 now, let's stop confusing newcomers (and me) with __wrong__ information. Is it bad to use `new` or not? I personally don't see any issue with it, nor with `+newWithString:`. – Iulian Onofrei Sep 14 '15 at 11:47
  • 2
    The link provided in the answer doesn't seem to work for me, so I don't know whether this is already addressed, but: does having the new method calling the alloc and init methods not merely add another stack push to the pipeline, and therefore makes the code run more slowly (even if the difference is negligible)? Or does the compiler address that? – Leo Flaherty Oct 02 '15 at 10:55
  • The link isn't working for me either, and downforeveryoneorjustme seems to indicate that I'm not the only one; unfortunately it looks like that site is gone for good. – jrh Jan 23 '19 at 01:24
145

Very old question, but I've written some example just for fun — maybe you'll find it useful ;)

#import "InitAllocNewTest.h"

@implementation InitAllocNewTest

+(id)alloc{
    NSLog(@"Allocating...");
    return [super alloc];
}

-(id)init{
    NSLog(@"Initializing...");
    return [super init];
}

@end

In main function both statements:

[[InitAllocNewTest alloc] init];

and

[InitAllocNewTest new];

result in the same output:

2013-03-06 16:45:44.125 XMLTest[18370:207] Allocating...
2013-03-06 16:45:44.128 XMLTest[18370:207] Initializing...
Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
radekEm
  • 4,617
  • 6
  • 32
  • 45
  • 5
    Excellent answer! Just wanna add that using +new is great for the cases where you only need to use -init and nothing more specialized like -initWithSomething:... – Christian Gossain Jan 05 '14 at 06:58
  • Unfortunately, this example is not proof that they are identical. It is just an example where they produce the same result. – Vince O'Sullivan May 07 '14 at 11:55
  • 13
    Unfortunately, this example is not proof that they are identical. It is just an example where they happen produce the same result. On the other hand, this proves that they are different... Taking the example above, modify "InitAllocNewTest.h" as follows: @interface InitAllocNewTest : NSObject -(instancetype) __unavailable init; @end `[[InitAllocNewTest alloc] init]` will not compile whilst `[InitAllocNewTest new]` is unaffected. (Apologies for lack of line breaks, etc.) – Vince O'Sullivan May 07 '14 at 12:02
  • 1
    @VinceO'Sullivan, good point. This means if one wants to make init unavailable, as in a singleton class, one should disable new as well. I won't touch here on whether singletons are good or bad. – user3099609 Mar 24 '15 at 16:23
  • I have a question from the above code. why "return [super init];"? generally init is a method where members of the class are initialized, why the pointer changes is very weird! – Pruthvidhar Rao Nadunooru Dec 14 '16 at 19:12
52

+new is equivalent to +alloc/-init in Apple's NSObject implementation. It is highly unlikely that this will ever change, but depending on your paranoia level, Apple's documentation for +new appears to allow for a change of implementation (and breaking the equivalency) in the future. For this reason, because "explicit is better than implicit" and for historical continuity, the Objective-C community generally avoids +new. You can, however, usually spot the recent Java comers to Objective-C by their dogged use of +new.

Barry Wark
  • 107,306
  • 24
  • 181
  • 206
  • 8
    Although this is often true, there is a camp in favor of terseness as well, in which case only being more explicit when there is a clear and present concern that warrants it. – Peter DeWeese Feb 26 '12 at 17:35
  • 31
    I downvoted this because `+new` has been around since the NeXT days. If anything `+new` is something of a sign of somebody who learned objc a long time ago; I see a lot of people who come fresh to the language, or who have even been writing it for years but clearly after the iOS boom, have no idea what `+new` means. Second, as `+new` is very old and from the NeXT days, Apple would be pretty insane to change it in a way that breaks old code, especially considering their own code bases are probably littered with it. – asveikau Jan 27 '13 at 04:12
  • I have no idea how Java is connected to this, coming from C/C++ background it was not that obvious for me what +new does, my first guess was that it's an alias for alloc. It's a good shortcut if you object doesn't have custom init method. – pronebird May 30 '13 at 15:36
  • 1
    I'm pretty sure the `new` idiom comes from Smalltalk. It's also used in Ruby, and both Objective-C and Ruby derive a lot of their syntax and conventions from Smalltalk. – Brendon Roberto Nov 08 '13 at 02:12
  • 3
    It only allows for a change in alloc. The docs explicitly state -init will be called. So it more depends on if you override alloc ever. – Kendall Helmstetter Gelner Apr 08 '14 at 05:44
  • 7
    I can't really imagine why a solution where you have to type MORE would be preferred (alloc init), especially in such a verbose language like Objective-C where saving keystrokes will save you time. Those "dogged Java developers" are just using their analytical skills to spend less time writing code instead of unnecessarily typing extra characters that produce the same functional result. – DiscDev Oct 30 '14 at 21:00
10

One Short Answere is:

  1. Both are same. But
  2. 'new' only works with the basic 'init' initializer, and will not work with other initializers (eg initWithString:).
user739711
  • 1,842
  • 1
  • 25
  • 30
10

Frequently, you are going to need to pass arguments to init and so you will be using a different method, such as [[SomeObject alloc] initWithString: @"Foo"]. If you're used to writing this, you get in the habit of doing it this way and so [[SomeObject alloc] init] may come more naturally that [SomeObject new].

Brian Campbell
  • 322,767
  • 57
  • 360
  • 340
4

I am very late to this but I want to mention that that new is actually unsafe in the Obj-C with Swift world. Swift will only create a default init method if you do not create any other initializer. Calling new on a swift class with a custom initializer will cause a crash. If you use alloc/init then the compiler will properly complain that init does not exist.

MurderDev
  • 157
  • 1
  • 10
3

For a side note, I personally use [Foo new] if I want something in init to be done without using it's return value anywhere. If you do not use the return of [[Foo alloc] init] anywhere then you will get a warning. More or less, I use [Foo new] for eye candy.

evdude100
  • 437
  • 4
  • 18
1

If new does the job for you, then it will make your code modestly smaller as well. If you would otherwise call [[SomeClass alloc] init] in many different places in your code, you will create a Hot Spot in new's implementation - that is, in the objc runtime - that will reduce the number of your cache misses.

In my understanding, if you need to use a custom initializer use [[SomeClass alloc] initCustom].

If you don't, use [SomeClass new].

Sangram Shivankar
  • 3,535
  • 3
  • 26
  • 38
Mike Crawford
  • 2,232
  • 2
  • 18
  • 28
  • 1
    I would argue with "if you need to use a custom initializer use [[SomeClass alloc] initCustom]". If you need a custom initialiser without any parameters, never do something like you are suggesting, just override the default `init` function, and use it `[[SomeClass alloc] init];` If you need parameters, still never do something like that, do `[[SomeClass alloc] initWith:...];`. Lastly, if you override the `init` function with a custom implementation, you can call `new` upon creating an object, and it will still call the custom `init` implementation. – dirtydanee Jan 01 '17 at 14:25