使用alloc init代替new

在学习Objective-C和阅读示例代码时,我注意到对象通常是用这种方法创建的:

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

而不是:

SomeObject *myObject = [SomeObject new];

这是有原因的吗,因为我读到它们是等价的?

107387 次浏览

这里有一堆原因:http://macresearch.org/difference-between-alloc-init-and-new

精选的有:

  • new不支持自定义初始化式(比如initWithString)
  • alloc-initnew更显式

一般的观点似乎是你应该使用任何你觉得舒服的东西。

通常情况下,你需要将参数传递给init,因此你将使用不同的方法,比如[[SomeObject alloc] initWithString: @"Foo"]。如果你习惯了这样写,你就会养成这样做的习惯,所以[[SomeObject alloc] init]可能比[SomeObject new]更自然。

在苹果的NSObject实现中,+new相当于+alloc/-init。这几乎不可能改变,但根据你的偏执程度,Apple的+new文档似乎允许在未来改变实现(并打破等价性)。出于这个原因,因为“显式优于隐式”,并且为了历史的连续性,Objective-C社区通常会避免+new。然而,你通常可以通过他们顽强地使用+new来发现Objective-C的最新Java来者。

作为旁注,我个人使用[Foo new],如果我想在init中做一些事情,而不使用它的返回值。如果你没有在任何地方使用[[Foo alloc] init]的返回值,那么你会得到一个警告。或多或少,我用[Foo new]来做花瓶。

一个简短的回答是:

  1. 两者都是一样的。但
  2. 'new'只适用于基本的'init'初始化式,而不是 与其他初始化式一起工作(例如initWithString:).

很老的问题,但我写了一些例子只是为了好玩-也许你会发现它有用;)

#import "InitAllocNewTest.h"


@implementation InitAllocNewTest


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


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


@end

在main函数中这两个语句:

[[InitAllocNewTest alloc] init];

而且

[InitAllocNewTest new];

得到相同的输出:

2013-03-06 16:45:44.125 XMLTest[18370:207] Allocating...
2013-03-06 16:45:44.128 XMLTest[18370:207] Initializing...

如果new可以帮你完成这个工作,那么它也会让你的代码稍微小一些。如果你在代码的许多不同的地方调用[[SomeClass alloc] init],你将在new的实现中创建一个热点——也就是说,在objc运行时中——这将减少缓存失败的数量。

在我的理解中,如果需要使用自定义初始化器,请使用[[SomeClass alloc] initCustom]

如果没有,使用[SomeClass new]

我很晚才提到这个,但我想说的是,这个新在oj - c和Swift的世界里实际上是不安全的。如果你没有创建任何其他初始化式,Swift只会创建一个默认的init方法。在使用自定义初始化项的swift类上调用new将导致崩溃。如果你使用alloc/init,那么编译器会正确地报错init不存在。