Is it possible to filter an NSArray by class?

安稳与你 提交于 2019-11-27 20:06:26

You could add a category to NSObject that adds a "cf_className" method, like so:

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

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

From there, you can use predicates like:

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

If you're on the Mac, you can just use -[NSObject className] instead of having to create the category. The iPhone doesn't have that method, hence the need for a category.

You can directly compare classes as well in your predicate.

But, it probably won't work as you would expect if you're trying to filter for objects that belong to class clusters or if you have subclasses.

For example, NSDate when instantiated is usually an __NSCFDate and NSString can be NSCFString as well as other specific private classes.

It's probably better to just loop through the set yourself and use -isKindOfClass: as the test.

IF you really want to use NSPredicate though you can do this. As an example, this would filter an array for all objects derived from NSString. If you wanted strict class membership you could replace isKindOfClass: with isMemberOfClass:.

Any selector that all objects in the collection implement, takes one argument and returns a BOOL should work though.

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

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

Starting in iOS 4 and Mac OS 10.6, one can use +[NSPredicate predicateWithBlock:] as well. For example:

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:.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!