是否可以按类过滤NSArray?

时间:2010-03-31 16:57:13

标签: objective-c cocoa cocoa-touch nsarray nspredicate

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

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

3 个答案:

答案 0 :(得分:74)

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

但是,如果您尝试过滤属于类集群的对象或者您有子类,它可能无法正常工作。

例如,实例化时NSDate通常为__NSCFDateNSString可以是NSCFString以及其他特定私有类。

最好自己循环设置并使用-isKindOfClass:作为测试。

IF 确实想要使用NSPredicate,但您可以这样做。作为示例,这将过滤从NSString派生的所有对象的数组。如果您想要严格的班级成员资格,可以将isKindOfClass:替换为isMemberOfClass:

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

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

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

答案 1 :(得分:25)

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

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

这允许您纯粹使用Objective-C表达谓词,而不是predicateWithFormat:所需的谓词语法。

答案 2 :(得分:22)

您可以向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没有这种方法,因此需要一个类别。