26

有没有办法构造一个谓词来按类类型过滤?

我目前遍历数组并检查每个对象的类。也许有更清洁的方法?

4

3 回答 3

77

您也可以在谓词中直接比较类。

但是,如果您尝试过滤属于类集群的对象或如果您有子类,它可能不会像您期望的那样工作。

例如,NSDate当实例化时通常是一个__NSCFDate并且NSString可以是NSCFString以及其他特定的私有类。

最好自己循环遍历集合并-isKindOfClass:用作测试。

如果真的想使用,NSPredicate虽然你可以这样做。例如,这将为从NSString. 如果您想要严格的班级成员资格,您可以替换isKindOfClass:isMemberOfClass:.

集合中的所有对象都实现的任何选择器都接受一个参数并返回 aBOOL应该可以工作。

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

NSLog(@"%@", [mixedArray filteredArrayUsingPredicate:predicate]);
于 2010-03-31T20:37:00.980 回答
29

从 iOS 4 和 Mac OS 10.6 开始,也可以使用+[NSPredicate predicateWithBlock:]。例如:

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

This allows you to express your predicates purely in Objective-C rather than the predicate syntax required by predicateWithFormat:.

于 2013-11-10T19:43:57.017 回答
24

您可以向 NSObject 添加一个添加“cf_className”方法的类别,如下所示:

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

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

从那里,您可以使用如下谓词:

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

如果您在 Mac 上,您可以直接使用-[NSObject className]而不必创建类别。iPhone 没有这种方法,因此需要一个类别。

于 2010-03-31T17:28:42.023 回答