使用alloc init而不是new

wil*_*lc2 337 oop objective-c

学习Objective-C并阅读示例代码,我注意到对象通常是使用以下方法创建的:

SomeObject *myObject = [[SomeObject alloc] init];
Run Code Online (Sandbox Code Playgroud)

代替:

SomeObject *myObject = [SomeObject new];
Run Code Online (Sandbox Code Playgroud)

是否有理由这样做,因为我已经读到它们是等同的?

Jer*_*ley 286

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

一些选定的是:

  • new不支持自定义初始值设定项(如initWithString)
  • alloc-init 比...更明确 new

一般意见似乎是你应该使用你喜欢的任何东西.

  • 如果你已经实现了`-initWithString`,那么没有什么可以阻止你实现`+ newWithString:`.虽然不常见.就个人而言,当指定的初始化程序是`init`时,我总是使用`new`,只是太短而且很甜. (85认同)
  • 我知道这是一个旧线程,但我只想强调你_should not_实现`+ newWithString:`.这打破了关注点的分离.因为当你只想使用`-init`时,没有理由不使用`+ new`. (11认同)
  • 如果您的类使用-init作为指定的初始值设定项,+ new将调用它.Jeremy所指的是你有一个不是-init的自定义初始化程序.-initWithName :,例如. (7认同)
  • @JonathanSterling:Apple有很多例子,他们似乎正在做你建议的事情; 例如`[[NSString alloc] initWithFormat:...]`和`[NSString stringWithFormat:...]`都是等价的.你是说苹果违反了关注点,不应该以这种方式实施吗?(注意:我不是试图居高临下;我只想获得更多信息,并且知道跟苹果公司的领导有时是个坏主意.) (6认同)
  • 在我看来,自定义初始化器是一个令人信服的理由,支持[[alloc] init]].谢谢你的快速回答. (5认同)
  • @Senseful我相信可以追溯到ARC(或垃圾收集)之前的日子.这两件事我们不相同.stringWithFormat:将返回一个自动释放的字符串,而alloc:init:需要手动释放或自动释放,否则会导致内存泄漏. (5认同)
  • new()因此是一种方便的方法,因为没有涉及alloc和init吗?因此它不像alloc-> init那样返回一个自动释放的对象吗? (2认同)
  • 好的,现在是2015年,让我们停止让新手(和我)混淆__wrong__信息.使用`new`是不是很糟糕?我个人认为它没有任何问题,也没有看到`+ newWithString:`. (2认同)
  • 答案中提供的链接似乎对我不起作用,所以我不知道这是否已经解决,但是:确实调用alloc和init方法的新方法不仅仅是向管道添加另一个堆栈推送,因此使代码运行得更慢(即使差异可以忽略不计)?或编译器是否解决了这个问题? (2认同)

gui*_*eak 137

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

#import "InitAllocNewTest.h"

@implementation InitAllocNewTest

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

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

@end
Run Code Online (Sandbox Code Playgroud)

在main函数中都有两个语句:

[[InitAllocNewTest alloc] init];
Run Code Online (Sandbox Code Playgroud)

[InitAllocNewTest new];
Run Code Online (Sandbox Code Playgroud)

导致相同的输出:

2013-03-06 16:45:44.125 XMLTest[18370:207] Allocating...
2013-03-06 16:45:44.128 XMLTest[18370:207] Initializing...
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,这个例子并不能证明它们是相同的.这只是一个例子,它们会发生相同的结果.另一方面,这证明它们是不同的......以上面的例子为例,修改"InitAllocNewTest.h"如下:@interface InitAllocNewTest:NSObject - (instancetype)__ unavailable init; @end` [[InitAllocNewTest alloc] init]`将不会编译,而`[InitAllocNewTest new]`不受影响.(对于缺少换行符等道歉) (10认同)
  • 很好的答案!只是想补充一点,使用+ new非常适用于你只需要使用-init并且没有更专业的情况,例如-initWithSomething:... (5认同)

Bar*_*ark 52

+new相当于+alloc/-initApple的NSObject实现.这种情况不太可能发生变化,但根据您的偏执程度,Apple的文档+new似乎允许在未来改变实施(并打破等效性).出于这个原因,因为"显式优于隐式"而且对于历史连续性,Objective-C社区通常会避免+new.但是,您可以通过他们的顽固使用来发现最近的Java角色到Objective-C +new.

  • 我赞成这一点,因为自从NeXT时代以来,"+ new"已经存在.如果有什么东西"+ new"是某个人很久以前学过objc的迹象; 我看到很多人对这种语言感到新鲜,或者甚至已经写了多年,但显然在iOS热潮之后,他们不知道"+ new"的意思.其次,由于"+ new"非常古老,而且从NeXT时代开始,Apple会以破坏旧代码的方式改变它,特别是考虑到他们自己的代码库可能会被它弄乱. (26认同)
  • 虽然这通常是正确的,但也有一个支持简洁的阵营,在这种情况下,只有在有明确和现在的关注保证时才更明确. (8认同)
  • 我无法想象为什么一个你必须输入MORE的解决方案将是首选的(alloc init),特别是在像Objective-C这样的冗长语言中,保存击键可以节省你的时间.那些"顽固的Java开发人员"只是利用他们的分析技能花更少的时间编写代码,而不是不必要地键入产生相同功能结果的额外字符. (7认同)
  • 它只允许更改alloc.明确表示-init的文档将被调用.所以它更依赖于你是否覆盖了alloc. (3认同)

Bri*_*ell 8

通常,您需要传递参数init,因此您将使用不同的方法,例如[[SomeObject alloc] initWithString: @"Foo"].如果你习惯于写这篇文章,你会习惯这样做,所以[[SomeObject alloc] init]可能更自然地来[SomeObject new].


use*_*711 7

一个简短的回答是:

  1. 两者都是一样的.但
  2. 'new'仅适用于基本的'init'初始值设定项,不适用于其他初始值设定项(例如initWithString :).