2010-03-31 4 views
23

클래스 유형별로 필터링 할 술어를 구성하는 방법이 있습니까?클래스별로 NSArray를 필터링 할 수 있습니까?

현재 배열을 반복하여 각 객체의 클래스를 확인합니다. 어쩌면 깨끗한 방법이 있을까요?

+0

왜 다른 개체를 같은 배열에 배치하고 있습니까? –

+12

한 가지 이유는 추상 클래스의 배열이있는 경우입니다. 모든 Person 클래스를 가질 수 있지만 의사 또는 변호사를 필터링하려고합니다. – rob5408

답변

22

당신은 너무처럼 "cf_className"방법을 추가 NSObject의에 카테고리 추가 할 수 있습니다 : 당신이 경우

NSPredicate * p = [NSPredicate predicateWithFormat:@"cf_className = %@", aClass]; 
NSArray * filtered = [anArray filteredArrayUsingPredicate:p]; 

: 당신은 같은 조건을 사용할 수 있습니다, 거기에서

@interface NSObject (CFAdditions) 
- (NSString *) cf_className; 
@end 

@implementation NSObject (CFAdditions) 
- (NSString *) cf_className { 
    return NSStringFromClass([self class]); 
} 
@end 

을 Mac의 경우 범주를 생성하지 않고 -[NSObject className]을 사용할 수 있습니다. 아이폰에는 그런 방법이 없기 때문에 카테고리가 필요하다.

+8

self.class.description도 할 수 있습니다. –

+0

@BrianKing excellent point –

70

술어에서 클래스를 직접 비교할 수도 있습니다.

그러나 클래스 클러스터에 속한 객체를 필터링하려고하거나 하위 클래스가있는 경우 예상대로 작동하지 않습니다.

예를 들어, NSDate이 인스턴스화 된 경우 보통 __NSCFDate이고 NSStringNSCFString 일 수 있으며 기타 특정 개인 클래스 일 수 있습니다.

직접 설정을 반복하고 -isKindOfClass:을 테스트로 사용하는 것이 좋습니다.

당신이 정말는이 작업을 수행 할 수 있지만 NSPredicate를 사용하려면 경우. 예를 들어 NSString에서 파생 된 모든 객체에 대해 배열을 필터링합니다. 엄격한 반원 자격을 원하면 isKindOfClass:isMemberOfClass:으로 바꿀 수 있습니다.

컬렉션의 모든 개체가 구현하는 선택기는 하나의 인수를 취하고 BOOL을 반환합니다.

NSArray *mixedArray = {...}; 
NSPredicate *predicate = [NSPredicate predicateWithFormat: 
             @"self isKindOfClass: %@", 
             [NSString class]]; 

NSLog(@"%@", [mixedArray filteredArrayUsingPredicate:predicate]); 
+1

+1 셀렉터를 직접 술어에 넣는 것을 생각한 적이 없습니다. 산뜻한! –

+1

포지티브 프로그래밍 가이드 (형식 문자열에서이 작업을 수행하는 것이 기술적으로 문서화되지 않았 음을 의미)에는 언급되어 있지 않지만 사용자 지정 선택기 기능은 http://developer.apple.com/mac/library/에서 참조로 백업됩니다. documentation/Cocoa/Reference/Foundation/Classes/NSComparisonPredicate_Class/Reference/NSComparisonPredicate.html # // apple_ref/occ/clm/NSComparisonPredicate/predicateWithLeftExpression : rightExpression : customSelector : 매우 멋지다. –

+0

그래, 원래는 긴 방법으로 작성했지만 종달새에는 형식 문자열로 시도해보고 작동하는 것이 놀랍습니다. –

22

아이폰 OS 4 및 Mac OS 10.6부터, 하나는뿐만 아니라 +[NSPredicate predicateWithBlock:]를 사용할 수 있습니다. 예를 들어 :

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { 
    return [object isKindOfClass:[NSString class]]; 
}]; 

이것은 당신이 목표 - C보다는 predicateWithFormat:에서 요구하는 조건 구문에 순전히 당신의 술어를 표현 할 수 있습니다.

+4

이 사람은 더 많은 표를 얻습니다. –

관련 문제