간단히 말해서 nil은 객체 참조에, null은 그 밖의 포인터 자료형에 사용된다.
//nil 사용
MyClass *obj = nil
// null 사용
int *ptr = NULL;
Java 에서는 객체 참조값이 null 일 경우, NullPointerException이 발생하게 되지만, Objective-C의 경우는 Java와 달리 내부에서 null 확인작업이 이루어진다. 메시지 전송 과정에서 중앙 메시지 전송 함수가 수신자의 포인터 값을 확인하는데,
이 때 수신자의 포인터가 nil 값인 경우 메시지 전송 함수는 즉시 반환되기 때문이다.
Objective-C는 Exception은 발생시키지 않으나 메시지에 전달되는 인자는 정상적으로 진행된다.
증가연산자(++)가 사용되는 경우에도 메시지 수신 객체가 nil 이라 하더라고 인자값은 정상적으로 처리가 되버린다...
nil 수신자에 메세지를 전송할 경우 반환되는 값은 아래와 같다.
반환타입 | 반환 값 |
id | nil |
객체 포인터 | NULL |
BOOL | NO |
(unsigned)char | '\0' |
(unsigned)int | 0 |
(unsigned)long int | 0L |
(unsigned)long long int | 0LL |
float | 0.0f |
double | 0.0 |
long double | 0.0 |
반환 값으로 구조체를 넘겨받는 경우에는 nil 수신자가 정상적으로 동작하지 않는데, 이 경우 Java에서와 같이 메시지 전송 전 nil 여부를 확인할 필요가 있다.
nil 특성을 이용해 프로그램을 구성하려면 프로퍼티 접근자(property accessor), 부재중 동작(absent behavior), 없음의 일관성(consistency with nothing) 등의 세가지 원칙을 지키는 것이 좋다.
1) 프로퍼티 접근자
프로퍼티의 접근 메소드를 만들어 사용하면 프로퍼티 소유 객체의 값이 nil 인 경우에도 문제가 없다. 하지만 프로퍼티의 접근 메소드를 만들지 않고, myObject -> myProperty 와 같이 직접 접근을 하는 경우엔 메무리 주소 오류가 발생한다.
2) 부재중 동작
객체가 부재중(=nil)인 경우 상황에 따라 추가적인 동작을 지정해야 하는 경우가 있다.
-
로그 객체 : 로그 출력 객체가 설정되어 있다면 전달받은 메시지를 로그에 출력하고, nil로 설정되면 아무런 작업을 하지 않는다.
-
리스너 객체 : 리스너 객체는 설정된 상태에서만 변경된 정보에 대한 메시지를 전송한다. nil로 설정되면 더이상 변경 사항이 전달되지 않는다.
-
위임 객체 : 위임 객체는 설정된 상태에서만 위임 객체 기능을 호출하고 없으면 기본 기능만 호출한다.
3) 없음의 일관성
클래스의 프로퍼티에서는 0 또는 nil의 개념이 없는 객체로 일관되게 설계하는 것이 좋다. 프로퍼티를 긍적적인 값을 표현하게 정의하는 것이 좋다. 즉, isEmpty라는 메소드 대신 hasObject라는 메소드 형식으로 정의하는 것이 바람직하다.
'프로그래밍 > ios(Swift)' 카테고리의 다른 글
#include pods/target support files/pods-runner/pods-runner.debug.xcconfig (0) | 2020.04.01 |
---|---|
Notification Center (0) | 2020.03.22 |