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