새로운 대신 alloc init 사용


344

Objective-C를 배우고 샘플 코드를 읽으면 객체가 일반적 으로이 방법을 사용하여 생성됩니다.

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

대신에:

SomeObject *myObject = [SomeObject new];

그것들이 동등한 것을 읽었을 때 이것에 대한 이유가 있습니까?


12
나는 그것이 가능하다는 것을 몰랐다! 내가 읽은 모든 자료는 새로운 키워드와 같은 척도 존재하지 않습니다!
Jonathan

78
실제로 "new"는 Objective-C의 키워드는 아니지만 NSObject는 단순히 "alloc"및 "init"를 호출하는 "new"클래스 메소드를 구현합니다.
Don McCaughey

3
조나단, 그게 내 질문을 촉발시킨 것입니다. 그것들은 기능적으로 동일 할 수 있지만 [[alloc] init]는 분명히 지배적 인 관용구입니다.
willc2

1
Apple (iTunes Stanford 강의 중 하나에서 기억할 수있는 것)은 대신 ​​alloc init을 사용하여 현재 진행중인 프로세스를 이해할 수 있도록 권장합니다. 그들은 또한 샘플 코드에서 새로운 것을 많이 사용하지 않으므로 alloc init은 Apple이 홍보하려고하는 일반적인 좋은 습관 인 것 같습니다.
PostCodeism

답변:


290

여기에 여러 가지 이유가 있습니다 : http://macresearch.org/difference-between-alloc-init-and-new

선택된 것들은 :

  • new커스텀 이니셜 라이저를 지원하지 않습니다 (예 initWithString:)
  • alloc-init 보다 명백하다 new

일반적인 의견은 자신이 편한 것을 사용해야한다는 것입니다.


8
클래스가 지정된 초기화 자로 -init를 사용하면 + new가 호출합니다. Jeremy가 말하는 것은 -init가 아닌 커스텀 이니셜 라이저가있는 경우입니다. 예를 들어 -initWithName :
bbum

87
+newWithString:이미 구현 한 경우 구현 을 방해하는 것은 없습니다 -initWithString. 그래도 흔한 일은 아닙니다. 개인적으로 나는 new지정된 초기화 프로그램이 항상 init짧고 달콤 할 때 사용 합니다 .
PeyloW

11
나는 이것이 오래된 스레드라는 것을 알고 있지만 구현 해서는 안된다는 것을 강조하고 싶습니다 +newWithString:. 그것은 우려의 분리를 깨뜨립니다. -init어쨌든 사용하고 싶을 때만을 사용 하지 않는 이유는 없습니다 +new.
Jonathan Sterling

7
@JonathanSterling : Apple은 여러분이 조언 한 것과 정확히 일치하는 것처럼 보이는 많은 인스턴스를 가지고 있습니다; 예 [[NSString alloc] initWithFormat:...][NSString stringWithFormat:...]모두 동일하다. 당신은 애플이 우려의 분리를 위반했다고 말하고 있습니까? 이런 식으로 구현해서는 안됩니까? (참고 : 나는
혼란스러워

6
@ 센스 나는 ARC (또는 가비지 수집) 전날로 거슬러 올라간다고 생각합니다. 이 두 가지는 우리가 동일하지 않습니다. stringWithFormat :은 자동 해제 된 문자열을 반환하지만 alloc : init :는 수동으로 해제 또는 자동 해제해야합니다. 그렇지 않으면 메모리 누수가 발생할 수 있습니다.
msfeldstein

139

아주 오래된 질문이지만 재미를 위해 몇 가지 예를 썼습니다. 아마도 유용 할 것입니다.)

#import "InitAllocNewTest.h"

@implementation InitAllocNewTest

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

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

@end

주요 기능에서 두 진술 :

[[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...

5
훌륭한 답변! 그냥 + init를 사용하면 -init 만 사용하면되고 -initWithSomething과 같이 더 특별한 것은 필요하지 않은 경우에 좋습니다.
cgossain

불행하게도,이 예는 이들이 동일하다는 증거가 아닙니다. 동일한 결과를 생성하는 예일뿐입니다.
빈스 오 설리번

10
불행하게도,이 예는 이들이 동일하다는 증거가 아닙니다. 동일한 결과를 낳는 사례 일뿐입니다. 반면에, 이것은 서로 다르다는 것을 증명합니다 ... 위의 예를 들어, 다음과 같이 "InitAllocNewTest.h"를 수정하십시오 : @interface InitAllocNewTest : NSObject-(instancetype) __unavailable init; 영향을받지 [[InitAllocNewTest alloc] init]않으면 @end 가 컴파일되지 [InitAllocNewTest new]않습니다. (줄 바꿈 등이없는 것에 대한 사과)
Vince O'Sullivan

1
@ VinceO'Sullivan, 좋은 지적입니다. 이것은 싱글 톤 클래스 에서처럼 init를 사용할 수 없게하려면 new도 비활성화해야한다는 것을 의미합니다. 싱글 톤이 좋은지 나쁜지는 여기에서 다루지 않겠습니다.
user3099609

위 코드에서 질문이 있습니다. 왜 "[수퍼 초기화]를 반환;"? 일반적으로 init는 클래스 멤버가 초기화되는 방법입니다. 왜 포인터 변경이 매우 이상합니까!
Pruthvidhar Rao Nadunooru

52

+new+alloc/-initApple의 NSObject구현 과 동일합니다 . 이것이 변경 될 가능성은 거의 없지만, 편집증 수준에 따라, Apple의 문서 +new는 향후 구현 변경 (및 동등성 중단)을 허용하는 것으로 보입니다. 이러한 이유로, "명시적인 것이 묵시적인 것보다 낫다"고 역사적 연속성을 위해 Objective-C 커뮤니티는 일반적으로 피 +new합니다. 그러나 일반적으로 Objective-C에 대한 최근의 자바 사용은 그들의 독단적 인 사용을 통해 확인할 수 +new있습니다.


8
이것은 종종 사실이지만, 간결함에 찬성하는 수용소도 있으며,이 경우이를 보장하는 명확하고 현재의 우려가있는 경우에만 더욱 분명해집니다.
Peter DeWeese

27
나는 +newNeXT 시절부터 주변에 있었기 때문에 이것을 하향 투표했습니다 . +new오래 전에 objc를 배운 사람의 표시 라면 무엇 인가? 나는 언어에 익숙해 지거나 수년 동안 글을 썼지 만 iOS 붐 이후 분명하게 많은 사람들이 무슨 +new의미 인지 알지 못합니다 . 둘째, +new매우 오래되고 NeXT 시절부터 애플은 오래된 코드를 깨뜨리는 방식으로 그것을 바꾸는 것이 미쳤습니다. 특히 자체 코드베이스가 아마도 어지럽다는 것을 고려할 때.
asveikau

1
나는 그 new관용구가 스몰 토크에서 온 것이라고 확신합니다 . Ruby에서도 사용되며 Objective-C와 Ruby는 모두 Smalltalk에서 구문과 규칙을 많이 파생시킵니다.
Brendon Roberto

3
할당량 만 변경할 수 있습니다. 문서에 명시 적으로 -init가 호출됩니다. 따라서 alloc을 재정의하는지 여부에 따라 다릅니다.
Kendall Helmstetter Gelner

7
키 입력을 저장하면 시간이 절약되는 Objective-C와 같은 장황한 언어에서 MORE를 입력 해야하는 솔루션이 선호되는 이유를 알 수는 없습니다. 이러한 "독점 Java 개발자"는 분석 기능을 사용하여 동일한 기능 결과를 생성하는 추가 문자를 불필요하게 입력하는 대신 코드 작성 시간을 단축합니다.
DiscDev

9

종종 인수를 전달해야 init하므로와 같은 다른 방법을 사용하게됩니다 [[SomeObject alloc] initWithString: @"Foo"]. 이 글을 쓰는 데 익숙하다면 이런 식으로 습관을들이는 것이 [[SomeObject alloc] init]더 자연 스럽습니다 [SomeObject new].


7

한 가지 짧은 답변은 다음과 같습니다.

  1. 둘 다 동일합니다. 그러나
  2. 'new'는 기본 'init'이니셜 라이저에서만 작동하며 다른 이니셜 라이저 (예 : initWithString :)에서는 작동하지 않습니다.

3

참고로, [Foo new]어디에서나 반환 값을 사용하지 않고 init에 무언가를하고 싶다면 개인적으로 사용 합니다. [[Foo alloc] init]어디에서든 반품을 사용하지 않으면 경고가 표시됩니다. 다소간, 나는 [Foo new]눈 사탕에 사용 합니다.


3

나는 이것에 매우 늦었지만 Swift 세계가있는 Obj-C에서는 실제로 새로운 것이 안전하지 않다고 언급하고 싶습니다. 다른 초기화 프로그램을 만들지 않으면 Swift는 기본 init 메소드 만 만듭니다. 사용자 정의 이니셜 라이저를 사용하여 신속한 클래스에서 새로 전화하면 충돌이 발생합니다. alloc / init를 사용하면 컴파일러는 init가 존재하지 않는다고 올바르게 불평합니다.


1

새로운 것이 당신을 위해 일한다면, 그것은 또한 코드를 약간 작게 만듭니다. [[SomeClass alloc] init]코드의 여러 곳에서 다른 방법으로 전화를 걸면 새로운 구현, 즉 objc 런타임에 핫스팟을 만들어 캐시 누락 수를 줄일 수 있습니다.

내 이해에 따라 사용자 정의 초기화 프로그램을 사용해야하는 경우 [[SomeClass alloc] initCustom].

그렇지 않으면을 사용하십시오 [SomeClass new].


1
"사용자 정의 초기화 프로그램을 사용해야하는 경우 [[SomeClass alloc] initCustom]을 사용하십시오." 매개 변수가없는 사용자 정의 이니셜 라이저가 필요한 경우 제안하는 것과 같은 작업을 수행하지 말고 기본 init기능을 재정의 하고 사용하십시오. [[SomeClass alloc] init];매개 변수가 필요한 경우 여전히 그렇게하지 마십시오 [[SomeClass alloc] initWith:...];. 마지막으로, init커스텀 구현으로 함수 를 재정의하면 new객체를 만들 때 호출 할 수 있으며 여전히 커스텀 init구현을 호출합니다 .
dirtydanee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.