다음과같은 포인터변수에 자신의 변수명 그대로 자기자신의 주소값을 할당하는 특이한 변수선언을 처음 볼 경우 당황스러울 것이다.
void *myVariableName = &myVariableName
하지만 이는 자기참조 포인터 혹은 유니크 컨텍스트 포인터(unique context pointer)라는 이름으로 불리는 엄연히 C/C++/Obj-C에서 유효한 문법이다. 이를 이용하여 컴파일타임에 유니크한 포인터값을 생성할 수 있어서 컨텍스트 구분을 위한 변수를 표현할때 매우 유용하게 사용될 수 있다.
해당 컨텍스트변수가 해당 파일 내에서만 사용할 경우.
.m
파일에 다음과같이 선언하면된다.
static void *MyContext = &MyContext;
만약 다른 파일에서도 사용되는 컨텍스트라면,
.h
파일에
extern void *MyContext;
.m
파일에
void *MyContext = &MyContext;
이러한 변수범위에 관한 내용은 C/C++에서 auto,static,extern 키워드의 의미 포스팅에 더 자세히 적어두었다.
특정 컨텍스트를 나타내기 위해 포인터를 이용하는경우 아래와같이 NSString
객체에 유니크 키를 넣어서 const
로 사용하는 경우도 많이 있다.
const NSString* MyContext = @“unique_key_my_context”;
하지만 string의 특성을 이용하여 string 자체의 값을 이용하는 추가 로직이 들어가지 않는다면, 자기참조 포인터변수를 이용하는것이 메모리 사용측면이나, 컨텍스트 비교시 속도 성능면에서도 더 좋고 코딩하기도 간편하다.
다음은 애플에서 제공하는 AVPlayerDemo 샘플프로젝트에서 자기참조 포인터로 KVO(Key-Value Observing)에 사용되는 컨텍스트를 구현한 형태이니 참고해보자.
static void *AVPlayerDemoPlaybackViewControllerRateObservationContext = &AVPlayerDemoPlaybackViewControllerRateObservationContext; static void *AVPlayerDemoPlaybackViewControllerStatusObservationContext = &AVPlayerDemoPlaybackViewControllerStatusObservationContext; static void *AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext = &AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext; // 옵저버 등록 - (id)init { ... [self.mPlayerItem addObserver:self forKeyPath:kStatusKey options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:AVPlayerDemoPlaybackViewControllerStatusObservationContext]; ... } // 옵저버 변화 감시지 해당 컨텍스트에 따라 다르게 동작 - (void)observeValueForKeyPath:(NSString*) path ofObject:(id)object change:(NSDictionary*)change context:(void*)context { /* AVPlayerItem "status" property value observer. */ if (context == AVPlayerDemoPlaybackViewControllerStatusObservationContext) { [self syncPlayPauseButtons]; } else if(context == AVPlayerDemoPlaybackViewControllerRateObservationContext) { ... } ... }