[objective-c] Objective-C에서 self = [super init]가 0이 아닌지 확인해야하는 이유는 무엇입니까?

Objective-C에서 init 메소드 작성에 대한 일반적인 질문이 있습니다.

초기화를 계속하기 전에 init 메소드가 self = [super init]가 아닌지 확인 해야하는 곳은 어디에서나 (Apple의 코드, 서적, 오픈 소스 코드 등) 알 수 있습니다.

init 메소드의 기본 Apple 템플리트는 다음과 같습니다.

- (id) init
{
    self = [super init];

    if (self != nil)
    {
        // your code here
    }

    return self;
}

왜?

init이 언제 nil을 반환 할 것인가? NSObject에서 init를 호출하고 다시 반환하면 실제로 무언가를 망쳐 놓아야합니까? 이 경우 프로그램을 작성하지 않을 수도 있습니다.

클래스의 init 메소드가 nil을 반환하는 것이 일반적입니까? 그렇다면 어떤 경우에 왜 그런가?



답변

예를 들면 다음과 같습니다.

[[NSData alloc] initWithContentsOfFile:@"this/path/doesn't/exist/"];
[[NSImage alloc] initWithContentsOfFile:@"unsupportedFormat.sjt"];
[NSImage imageNamed:@"AnImageThatIsntInTheImageCache"];

… 등등. (참고 : 파일이 존재하지 않으면 NSData에서 예외가 발생할 수 있습니다). nil을 리턴하는 것이 문제가 발생할 때 예상되는 동작이있는 영역이 상당히 많기 때문에 일관성을 위해 nil을 거의 항상 점검하는 것이 표준 관행입니다.


답변

이 특정 관용구는 모든 경우에 작동하기 때문에 표준입니다.

흔하지는 않지만 다음과 같은 경우가 있습니다.

[super init];

… 다른 인스턴스를 반환하므로 자체 할당이 필요합니다.

그리고 nil을 반환하는 경우가 있으므로 nil 확인이 필요하므로 코드가 더 이상 존재하지 않는 인스턴스 변수 슬롯을 초기화하지 않습니다.

결론은 사용하기 위해 문서화 된 올바른 패턴이며, 사용하지 않으면 잘못하고 있다는 것입니다.


답변

대부분의 클래스에서 [super init]의 반환 값이 nil이고 표준 사례에서 권장하는대로 확인한 다음 nil 인 경우 조기에 반환하면 기본적으로 앱이 여전히 올바르게 작동하지 않습니다. 당신도 그 불구하고, 그것에 대해 생각하는 경우 경우 (자기! = 전무) 검사 클래스의 적절한 작동을 위해, 거기, 당신이 실제로 시간의 99.99 % nil이 아닌 될 필요 자체를. 자, 어떤 이유에서든 [super init] nil을 반환했다고 가정합니다. 기본적으로 nil에 대한 검사는 기본적으로 클래스 호출자에게 벅을 넘겨주는 것으로 가정합니다. 성공한.

기본적으로, 내가 얻는 것은 99.99 %의 시간입니다 .if (self! = nil)는 벅을 전달자에게 넘겨주기 때문에 견고성 측면에서 아무것도 사지 않습니다. 실제로이 문제를 강력하게 처리하려면 실제로 전체 통화 계층 구조를 확인해야합니다. 그럼에도 불구하고 구매할 수있는 유일한 것은 앱이 더 깨끗하고 견고하게 실패한다는 것입니다. 그러나 여전히 실패 할 것입니다.

라이브러리 클래스가 [super init]의 결과로 임의로 nil을 반환하기로 결정했다면 어쨌든 거의 겁이 나고 라이브러리 클래스 작성자가 구현 실수를 한 것입니다.

앱이 훨씬 제한된 메모리에서 실행될 때 이것은 레거시 코딩 제안에 가깝습니다.

그러나 C 레벨 코드의 경우 일반적으로 여전히 NULL 포인터에 대해 malloc ()의 반환 값을 확인합니다. 반면 Objective-C의 경우, 반대로 증거를 찾을 때까지 if (self! = nil) 검사를 건너 뛸 것이라고 생각합니다. 왜 불일치가 발생합니까?

C 및 malloc 레벨에서 일부 경우 실제로 부분적으로 복구 할 수 있기 때문입니다. Objective-C에서 99.99 %의 경우에 [super init]가 nil을 반환하면 처리하려고해도 기본적으로 f *** ed입니다. 앱이 중단되고 여파를 처리하게 할 수도 있습니다.


답변

이것은 위의 의견에 대한 요약입니다.

수퍼 클래스가를 반환한다고 가정 해 봅시다 nil. 무슨 일이야?

컨벤션을 따르지 않으면

init메소드 중간에 코드가 충돌합니다 . ( init의의가없는 한)

수퍼 클래스가 nil을 리턴 할 수 있다는 것을 모르고 규칙을 따르는 경우 (대부분의 사람들은 여기에서 끝납니다)

인스턴스가이므로 다른 코드가 nil예상 되기 때문에 코드가 나중에 언젠가 충돌 할 것입니다. 또는 프로그램이 충돌하지 않고 예기치 않게 작동합니다. 이런! 넌 이걸 원해? 모르겠어요 …

규칙을 따르면 하위 클래스가 nil을 반환하도록 기꺼이 허용

코드 문서 (!)에는 “return … or nil”이라고 명시해야하며 나머지 코드는이를 처리하기 위해 준비해야합니다. 이제 말이됩니다.


답변

일반적으로 수업이에서 직접 파생되는 경우 NSObject필요하지 않습니다. 그러나 클래스가 다른 클래스에서 파생되는 경우 이니셜 라이저가을 반환 할 수 있고이 nil경우 이니셜 라이저가이를 캡처하여 올바르게 작동 할 수 있습니다.

그리고 네, 기록을 위해, 나는 모범 사례를 따르고 모든 수업, 심지어에서 직접 파생 된 수업에 쓰십시오 NSObject.


답변

당신은 맞습니다, 당신은 종종 글을 쓸 수 [super init]는 있지만, 그것은 단지 아무것도의 서브 클래스에서 작동하지 않을 것입니다. 사람들은 단지 가끔 필요의 경우에도, 단지 시간 코드의 하나 개의 표준 라인을 암기하고 모두를 사용하는 것을 선호하고, 따라서 우리는 표준 얻을 if (self = [super init])반환 전무의 가능성과 이외의 객체의 가능성을 모두 소요 self반환을 계정에.


답변

흔한 실수는

self = [[super alloc] init];

서브 클래스 생성자 / 초기화에서 원하지 않는 수퍼 클래스의 인스턴스를 반환합니다. 서브 클래스 메소드에 응답하지 않는 오브젝트를 다시 얻습니다. 혼동 될 수 있으며, 메소드 나 ID를 찾을 수없는 응답에 대한 혼란스러운 오류가 발생합니다.

self = [super init]; 

서브 클래스의 멤버를 설정하기 전에 슈퍼 클래스에 멤버 (변수 또는 다른 객체)가 먼저 초기화되어야하는 경우 필요합니다 . 그렇지 않으면 objc 런타임은 그것들을 모두 0 또는 nil 로 초기화합니다 . ( ANSI C와 달리 메모리 청크를 전혀 지우지 않고 할당하는 경우가 많습니다 )

그렇습니다. 메모리 부족 오류, 구성 요소 누락, 리소스 획득 실패 등으로 인해 기본 클래스 초기화에 실패 할 수 있으므로 nil 검사는 현명하며 몇 밀리 초도 걸리지 않습니다.