Есть ли способ построить предикат для фильтрации по типу класса?
В настоящее время я просматриваю массив и проверяю класс каждого объекта. Может быть, есть более чистый способ?
Есть ли способ построить предикат для фильтрации по типу класса?
В настоящее время я просматриваю массив и проверяю класс каждого объекта. Может быть, есть более чистый способ?
Вы можете добавить категорию в 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 нет этого метода, следовательно, нужна категория.
Вы можете напрямую сравнивать классы и в своем предикате.
Но, вероятно, это не сработает, как вы ожидали бы, если вы пытаетесь фильтровать объекты, принадлежащие кластеру классов, или если у вас есть подклассы.
Например, NSDate
при создании экземпляра обычно __NSCFDate
и NSString
может быть NSCFString
, а также других конкретных частных классов.
Вероятно, лучше всего просто выполнить цикл через набор и использовать -isKindOfClass:
в качестве теста.
IF, вы действительно хотите использовать NSPredicate
, хотя вы можете это сделать. В качестве примера это будет фильтровать массив для всех объектов, полученных из NSString
. Если вы хотите строгое членство в классе, вы можете заменить isKindOfClass:
на isMemberOfClass:
.
Любой селектор, который реализует все объекты в реализации коллекции, принимает один аргумент и возвращает BOOL
.
NSArray *mixedArray = {...};
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"self isKindOfClass: %@",
[NSString class]];
NSLog(@"%@", [mixedArray filteredArrayUsingPredicate:predicate]);
Начиная с 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:
.