NSNull Category

44552 단어
txx 's blog
많은 개발 자 들 이 NSNull 에 의 해 구 속 된 적 이 있다 고 믿 습 니 다. 가장 흔히 볼 수 있 는 것 은 서버 가 돌아 온 json 입 니 다. 약속 한 사전, 배열, 숫자 입 니 다. 결 과 는 빈 값 으로 돌아 갑 니 다.
 
이 럴 때 NSJSONserialization 은 자동 으로 NSNull 로 바뀐다.dict [@ "hello"] 를 다시 사용 하면 exception 이 발생 하여 프로그램 이 무 너 집 니 다.
 
그럼 어떻게 처리 할 까요?
내 가 했 던 방법
매크로 를 써 서 되 돌아 오 는 이 클래스 가 NSNull 클래스 인지 아 닌 지 판단 합 니 다. 즉, isKindOfClass 입 니 다.
 
가장 간단 한 방법
다 들 아 실 거 라 고 믿 습 니 다. [NSNull null] 하나 가 아 닙 니 다.
공장 방법
단일 모드, 그러면 할당 한 이 포인터 가 [NSNull null] 인지 아 닌 지 직접 판단 하면 됩 니 다.
 
그럼 문제 가 생 겼 습 니 다. 컴 파일 러 에 warning 이 하나 더 생 겨 서 귀 찮 습 니 다.
 
... 에 있다
이 글 에는 여러 가지 방법 이 소개 되 어 있다.

  
  
  
  
  1. - (void)someMethod 
  2.     NSString *aString = @"loremipsum"
  3.  
  4.     // This will complain: "Comparison of distinct pointer types ('NSString *' and 'NSNull *')" 
  5.     if (aString != [NSNull null]) 
  6.     { 
  7.  
  8.     } 
  9.  
  10.     // This works (at least for strings), but isEqual: does different things  
  11.     // for different classes, so it's not ideal 
  12.     if ([aString isEqual:[NSNull null]]) 
  13.     { 
  14.  
  15.     } 
  16.  
  17.     // If you cast it to the class you're comparing against 
  18.     // then you're good to go 
  19.     if (aString != (NSString *)[NSNull null]) 
  20.     { 
  21.  
  22.     } 
  23.  
  24.     // But we can also just cast it to id and 
  25.     // that works generically 
  26.     if (aString != (id)[NSNull null]) 
  27.     { 
  28.  
  29.     } 
  30.  
  31.     // The thing that would be really cool, 
  32.     // would be [NSNull null] returning 
  33.     // id (like in the sample category below). 
  34.     // Wouldn't count on that one though. 
  35.     if (aString != [NSNull idNull]) 
  36.     { 
  37.  
  38.     } 

 
이것들 은 모두 매우 아름 다운 해결 방안 이 아니다. 이 글 의 저 자 는 추천 했다.

  
  
  
  
  1. @interface NSNull (idNull) 
  2. + (id)idNull; 
  3. @end 
  4. @implementation NSNull (idNull) 
  5. + (id)idNull { return [NSNull null]; } 
  6. @end 

 
혹시

  
  
  
  
  1. if ([[NSNull null] isEqual:aString]) 
  2.  

 
최종 해결 방안
위의 방법 은 모두 한 번 판단 해 야 하 는 지, 아니면 매우 우아 하지 않 은 지, 왜 일 까? 우 리 는 NULL, nil 처럼 직접 사용 할 수 없 는 지, 아니면 판단 해 야 하 는 지, 여기 서 가장 아름 다운 방법 을 추천 합 니 다.
 
진 항 은 하 나 를 제공 했다.
gist
 
나 는 나의 octopress 의 gist 플러그 인 이 끊 어 진 것 을 발견 하고 바로 붙 여 놓 았 다.

  
  
  
  
  1. #define NSNullObjects @[@"",@0,@{},@[]] 
  2.  
  3. @interface NSNull (InternalNullExtention) 
  4. @end 
  5.  
  6. @implementation NSNull (InternalNullExtention) 
  7.  
  8. - (NSMethodSignature*)methodSignatureForSelector:(SEL)selector 
  9.     NSMethodSignature* signature = [super methodSignatureForSelector:selector]; 
  10.     if (!signature) { 
  11.         for (NSObject *object in NSNullObjects) { 
  12.             signature = [object methodSignatureForSelector:selector]; 
  13.             if (signature) { 
  14.                 break
  15.             } 
  16.         } 
  17.  
  18.     } 
  19.     return signature; 
  20.  
  21. - (void)forwardInvocation:(NSInvocation *)anInvocation 
  22.     SEL aSelector = [anInvocation selector]; 
  23.  
  24.     for (NSObject *object in NSNullObjects) { 
  25.         if ([object respondsToSelector:aSelector]) { 
  26.             [anInvocation invokeWithTarget:object]; 
  27.             return
  28.         } 
  29.     } 
  30.  
  31.     [self doesNotRecognizeSelector:aSelector]; 
  32. @end 

 
고 급 스 럽 고 패기 있 는 방법 으로 이상 상황 을 처리 함으로써 이 기능 을 실현 한다.
 
여기 하나 더 제공 합 니 다.
일본 인의 포장 방안:

  
  
  
  
  1. #import "NSNull+OVNatural.h" 
  2.  
  3. @implementation NSNull (OVNatural) 
  4. - (void)forwardInvocation:(NSInvocation *)invocation 
  5.     if ([self respondsToSelector:[invocation selector]]) { 
  6.         [invocation invokeWithTarget:self]; 
  7.     } 
  8.  
  9. - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector 
  10.     NSMethodSignature *sig = [[NSNull class] instanceMethodSignatureForSelector:selector]; 
  11.     if(sig == nil) { 
  12.         sig = [NSMethodSignature signatureWithObjCTypes:"@^v^c"]; 
  13.     } 
  14.     return sig; 
  15.  
  16. @end 

 
[NSMethodSignature signature WithObjCTypes: "@ ^ vc"] 의 기능 에 대해 서 는 다음 두 글 을 참고 할 수 있 습 니 다.
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
http://nshipster.com/type-encodings/

좋은 웹페이지 즐겨찾기