티스토리 뷰

Mobile/iOS

nil이란?

out of coding 2014. 3. 3. 10:08

Objective-C의 nil과 NULL이라는 상수는 기술적으로 혼용이 가능하다.

일반적으로 nil은 객체 참조에 사용되고, NULL은 그 밖의 다른 포인터 자료형에 사용된다.

(예 DClass* dClass = nil, int* dInt = NULL)


중요한 부분은 자바에서는 객체 참조값이 null이면 NullPointerException이 발생하여서, 문제가 생기게 되는데,

Objective-C는 이런 부분이 발생하지 않게 되어 있다. 헐. 이유는 ... 

Objective-C는 메시지 전송과정에서 중앙 메시지 전송 함수가 수신인의 포인터 값을 확인하여서, 수신자 포인터가 null이면 메시지 전송함수는 즉시 반환되기 때문.

즉, 메시지 수신 객체가 nil 값이라도 Exception이 발생하지 않는다. 단. 리턴형이 존재하는 경우에는 0이나 nil 또는 NO값을 반환한다. (자료형에 따라서 다를듯.)

어마어마하게 편하긴 한데... 자바와는 다른 기법으로, 이 녀석을 처리를 해야겠구만. 양날의 검이겠지만 null을 체크하지 않으니깐. 코드는 편해질듯.


그래서 어마어마하게 편한데에 비해서 단점이 있을거라 생각이 들어서 봤더니.

일단 Exception은 발생을 하지 않지만, 메시지에 전달되는 인자는 정상적으로 진행된다. 이것이 무슨이야기이냐...

[[dClass setLevel] value++];

이런식이 되었을 경우에는. value는 증가를 한다는 소리다.


nil수신자에 메시지를 전송할 경우 반환되는 값

반환타입

반환값 

 id

nil 

 객체 포인터

NULL 

 BOOL

NO 

 (unsigned)char

'\0' 

 (unsigned)int

 (unsigned)long int

0L 

 (unsigned)long long int

0LL 

 float

0.0f; 

 double

0.0 

 long double

0.0 

머... 대충 예상하는 값들이 넘어오게 된다. 참고만 하면 될듯.


보면 알겠지만, 반환값으로 구조체를 넘겨받는 경우에는 앞에서 설명한 nil수신자 처리가 정상적으로 동작하지 않는다.

따라서 이 경우에는 자바에서처럼 메시지를 전송하기 전에 수신자의 nil여부를 확인해야 한다. CGRect등의 구조체는 어플리케이션에서 많이 사용되므로 주의할 필요가 있다.

(구조체를 반환하는 메시지 전송의 경우, 구조체가 하드웨어 레지스터를 통해 반환되는 경우는 예외라고 한다. 음? 이에 대한 확인은 API Function Calling Guide를 통해 확인가능하다고 하는데, 난 아직 이게 무슨 소리인지는 모른다.)

아무튼 중요한 프로그램 작성에 대한 부분으로 넘어가자면. nil의 특성을 고려해 프로그램을 구성한다면 다음의 세가지 원칙을 지키는것이 바람직할것이다.

  • 프로퍼티 접근자 생성
프로퍼티의 접근 메소드를 만들어 사용하면 프로퍼티 소유 객체의 값이 nil인 경우에도 [dClass dProperty]와 같이 사용이 가능하다. (애플에서 권장하는 방식)
그러나 프로퍼티의 접근 메소드를 만들지 않고, dClass->dProperty로 코드를 작성할 경우에는 프로퍼티 소유 객체 dClass가 nil이면 프로그램이 종료된다.
  • 부재중 동작 패턴?

객체가 부재중, 즉 nil일때 상황에 따라 추가적인 동작을 지정해야 하는 경우가 존재한다.

NSLock* lock;

-(void) method_01

{

    [lock lock];

        ...

    [lock unlock];

}


-(void) method_02

{

    [lock lock];

        ...

    [lock unlock];

}


-(void) makeThreadSafe

{

    lock = [NSLock new];

        ...

}

처음에는 lock 변수는 nil로 설정되어 있기 때문에, [lock lock],[lock unlock]은 아무런 작업을 하지 않는다. 실제로 스레드 안정성을 확보할 필요가 없을때 의미가 있다.

그러나 다중 스레드로 동작하는 환경에서는 스레드 안정성을 위해서, makeThreadSafe메소드를 호출해 lock변수에 객체를 만들어 넣을수 있다.

위처럼, 객체가 nil일 경우와 그렇지 않을 경우의 용도를 고려해서, 프로그래밍을 해야 할 필요가 있다. 아래의 상황을 참고하자.

      • 로그 객체 : 로그 출력 객체가 설정되 있다면 전달받은 메시지를 로그에 출력하고, 로그 객체가 없다면 로그 관련 작업을 하지 않음.
      • 리스너 객체 : 리스너가 설정된 상태에서만 변경된 정보에 대한 메시지가 전송된다. 이미 리스너가 설정된 경우, nil로 재설정하면 더 이상 변경사항이 전달되지 않는다.
      • 위임 객체 : 위임 객체가 있다면 위임 객체의 기능을 호출하고 없다면 기본 기능을 사용한다.
  • 없음의 일관성

프로퍼티에서는 0또는 nil의 개념을 없는 객체의 개념과 일관되게 설계하는것이 좋다. 즉, 프로퍼티가 부정적인 값보다 긍정적인 값을 표현하도록 프로퍼티를 정의하는 것이 좋은 습관이다.

예로. isEmpty보다는 hasObject가 맞다는것이다.

또한 자바와는 다르게 컬렉션 클래스에 nil을 값이나 키로 지정할수 없다고 한다. 흠... 당연하다 싶기는 한데. 오류가 나는것인가.


nil을 잘 활용하면 엄청나게 편할것 같은데, 조심해서 사용하기는 해야할것 같다.

안드로이드보다 훨씬 편한 개발 환경이다. 알면알수록 더더욱.

'Mobile > iOS' 카테고리의 다른 글

@selector  (0) 2014.03.05
ARC 에러  (0) 2014.03.05
@protocol  (0) 2014.02.28
Category  (0) 2014.02.28
동적 형을 다루는 메소드  (0) 2014.02.28
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함