Есть ли способ создать предикат для фильтрации по типу класса?
В настоящее время я просматриваю массив и проверяю класс каждого объекта. Может есть способ чище?
Есть ли способ создать предикат для фильтрации по типу класса?
В настоящее время я просматриваю массив и проверяю класс каждого объекта. Может есть способ чище?
Вы можете добавить категорию в 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]);
linkedAccounts
ко многим, и я хочу найти тот, который относится к классу FacebookAccount
.
- person ma11hew28; 04.12.2011
Начиная с 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:
.