2011-09-28 1 views
1

개체가 NSNotification인지 확인해야합니다. NSNotification인지 또는 NSNotification의 하위 클래스인지 구분할 때 하위 클래스인지 여부는 알기에 충분하지 않습니다. 그래서 테스트 유형 NSNotification

나는 다음과 같은 구별 할 필요가 정교 :

문제는 NSNotifications가 있다는 것입니다

  1. NSConcreteNotification
  2. NSNotification의 서브 클래스 (그러나 NSConcreteNotification) 실제로 NSConcreteNotifications 및 NSConcreteNotification은 개인 클래스이므로 테스트 할 때 사용할 수 없습니다. 필요에 따라이 NSConcreteNotifications 사용

    [object isMemberOfClass:NSClassFromString(@"NSConcreteNotifications")]; 
    

    변경 다른 클래스의 이름을 문자열 인 경우

    [object isMemberOfClass:[NSNotification class]];` 
    

    테스트 : ID 객체를 테스트하려면

    [object isMemberOfClass: [NSNotification class]] // returns NO in both cases 
    [object isKindOfClass: [NSNotification class]] // returns YES in both cases 
    
+0

테스트 대상은 NSNotification no의 하위 클래스입니까? – Geoffroy

+0

objective-C의 isMemberOfClass 메소드를 사용할 수 있습니다. 참조하시기 바랍니다 [isMemberOfClass] [1] [1] : http://stackoverflow.com/questions/2045561/objective-c-iskindofclass-missunderstanding – Naved

+0

1. NSConcreteNotification 또는 2.이 될 수있는 객체 NSNotification의 서브 클래스. 나는 그 차이를 말할 필요가있다. – Undistraction

답변

2

설명하는대로 NSNotification의 하위 클래스를 지정할 이유가 없습니다. 첫째, NSNotification은 이미 userInfo 사전을 가지고 있습니다. 거기에 원하는 데이터를 넣을 수 있습니다. 원한다면 범주 방법을 사용하여 해당 사전을 읽고 쓸 수 있습니다 (항상이 작업을 수행함). 예를 들어, 내가하고 싶은 아주 흔한 일은 어떤 물체를 따라 간다는 것입니다 (예 : RNMessage).그래서 다음과 같습니다 카테고리 생성 :

@interface NSNotificationCenter (RNMessage) 
- (void)postNotificationName:(NSString *)aName object:(id)anObject message:(RNMessage *)message; 
@end 

@interface NSNotification (RNMessage) 
- (RNMessage *)message; 
@end 

static NSString * const RNMessageKey = @"message"; 

@implementation NSNotificationCenter (RNMessage) 
- (void)postNotificationName:(NSString *)aName object:(id)anObject message:(RNMessage *)message { 
    [self postNotificationName:aName object:anObject userInfo:[NSDictionary dictionaryWithObject:message forKey:RNMessageKey]; 
} 
@end 

@implementation NSNotification (RNMessage) 
- (RNMessage *)message { 
    return [[self userInfo] objectForKey:RNMessageKey]; 
} 

으로 @hypercrypt 노트, 당신은 또한 바르를 생성하지 않고 임의의 객체에 데이터를 첨부 관련 참조를 사용할 수 있습니다,하지만 NSNotification로입니다 userInfo 사전을 사용하는 것이 훨씬 간단합니다. NSLog을 사용하여 알림을 인쇄하는 것이 훨씬 쉽습니다. 쉽게 직렬화 할 수 있습니다. 쉽게 복사 할 수 있습니다. Etc. 관련 참조는 훌륭하지만 멀리 떨어질 수있는 경우 피해야하는 작은 코너 케이스를 많이 추가합니다.

+0

아주 좋습니다. 이것은 정말로 도움이됩니다. 매우 감사. – Undistraction

1

NSNotification 사용하는 것입니다 ...

그런 다음 'NSNotification의 하위 클래스' (하지만 NSConcreteNotification '이 아닙니다.

다음 중 하나를

if ([object isMemberOfClass:NSClassFromString(@"NSConcreteNotifications")]) 
{ 
    // It's a NSConcreteNotifications... 
} 
else if ([object isKindOfClass:[NSNotification class]]) 
{ 
    // It's an NSNotification (or subclass) but not an NSConcreteNotifications 
} 

또는

if ([object isKindOfClass:[NSNotification class]] && ![object isMemberOfClass:NSClassFromString(@"NSConcreteNotifications")]) 
{ /* ... */ } 

당신이 NSNotification의 당신이 Associative References에 보일 것입니다에 속성을 추가 할 경우

.

기본 개념은 다음과 같습니다

static const char objectKey; 
- (id)object 
{ 
    return objc_getAssociatedObject(self, &objectKey); 
} 

- (void)setObject:(id)object 
{ 
    objc_setAssociatedObject(self, &objectKey, object, OBJC_ASSOCIATION_RETAIN); 
} 
+0

답장을 보내 주셔서 감사합니다. 하지만 문자열을 사용하는 것은 실제로 그렇게 안전하지 않은 것처럼 보입니다. 우리가 그런 간단한 작업을 위해 문자열을 하드 코딩해야한다는 것이 기괴한 것 같습니다. – Undistraction

+0

왜 둘을 구별해야합니까? – hypercrypt

+0

알림을 명령에 매핑하고 있기 때문에이 옵션을 강력하게 입력하고 싶습니다. 문자열 (알림의 이름)에 의존하는 것은 제 의견으로는 좋지 않은 방법입니다. – Undistraction

1

하는 것은 정말 나쁜 생각처럼 들린다. 알림을 처음 받으면 알림 콜백 메서드에 대한 명시적인 인수로 전달되므로 알림의 유형을 이미 알고 있습니다. 다른 개체의 강력한 형식의 속성으로 알림을 저장하거나 컬렉션에 추가하는 경우 사전에 적절한 키 아래에 삽입하거나 형식 정보를 유지하지 않는 다른 메서드에 알림을 전달하여 더 쉽게 만들 수 있습니다 나중에 확인하십시오.

개인 API에 대한 종속성 (개인 클래스의 이름 포함)을 작성하면 코드가 더 취약 해지고 이후 릴리스에서 중단 될 가능성이 높아집니다. 분명히, 이러한 클래스가 사적인 이유 중 하나는 Apple 엔지니어가 적합하다고 생각하는대로 쉽게 변경할 수 있도록하는 것입니다. 예를 들어 NSArray 및 NSMutableArray에 사용되는 구체적인 하위 클래스는 최근 SDK 릴리스에서 변경되었습니다.

+0

나는 그것이 나쁜 생각이라는 것을 충분히 이해합니다. 대안. 커스텀 프로퍼티를 가진 알림을 사용하고 싶습니다. 즉, NSNotification을 하위 클래스로 분류 할 수 밖에 없다는 것을 의미합니다. 나의 요구 사항 중 하나는 통지를받을 때 NSNotification 또는 NSNotification의 서브 클래스인지 여부를 확인할 수 있으므로 적절하게 행동 할 수 있습니다. – Undistraction

+1

관련 객체를 사용하여 카테고리를 사용하여 서브 클래스를 만들지 않고 속성을 추가 할 수 있습니다 ... – hypercrypt

+0

카테고리에서 속성을 sythesize 할 수 없다는 인상을 받고 있었습니까? – Undistraction

1

다른 사람들도 지적했듯이 개인 클래스의 이름을 사용하는 것은 좋지 않습니다. 특정 하위 클래스를 찾고 있다면 해당 클래스를 명시 적으로 확인할 수 있습니다.

[notification isMemberOfClass:[MyNotificationSubclass class]]; 

여러 개의 명령문을 사용하여 여러 하위 클래스를 검사 할 수 있지만 약간 복잡 할 수 있습니다. 이 방법은 새 클래스를 추가 할 때마다 변경해야합니다. 찾고있는 기능을 알림이 지원하는지 여부를 나타내는 읽기 전용 속성을 정의하는 것이 더 좋을 수 있으므로 클래스의 기능만큼 클래스에 의존하지는 않습니다. NSNotification에서이 속성에 대해 NO을 단순히 반환하는 범주를 사용할 수 있으며 기능이있는 하위 클래스는 YES을 반환하는 메서드를 재정의합니다. 를 지원하는 서브 클래스에서

@interface NSNotification (MyFeature) 
@property (readonly) BOOL hasMyFeature; 
@end 

@implementation NSNotification (MyFeature) 
- (BOOL)hasMyFeature { 
    return NO; 
} 
@end 

:

- (BOOL)hasMyFeature { 
    return YES; 
} 
- (void)performMyFeature { 
    ... 
} 
이것은 또한 당신이 알림 hasMyFeature에 대해 반환되는 플래그를 변경하여 활성화 기능이 있는지 여부를 변경할 수 있도록 할

하고 확인 코드는 다음과 같습니다 :

if(notification.hasMyFeature) [notification performMyFeature]; 
+0

관용적 (구현이 더 짧고, 사용하기가 더 짧음)은 아마도 if ([notification respondsToSelector : @selector (performMyFeature)]) [notification performMyFeature];'가 될 것이고 더 이상 'hasMyFeature' 속성이 필요 없을 것입니다. – Quuxplusone

+0

@Quuxplusone True. 지금 생각해 보면, 카테고리에 빈'performMyFeature' 메소드를 추가 할 수도 있습니다. 그렇다면 전혀 점검 할 필요가 없습니다. 그러나 나는 그 스타일을 그대로 두는 경우가 많습니다. 왜냐하면 나는 그 스타일을 선호하기 때문입니다. – ughoavgfhw