Есть ли способ построить предикат для фильтрации по типу класса?Можно ли фильтровать NSArray по классам?
В настоящее время я просматриваю массив и проверяю класс каждого объекта. Может быть, есть более чистый способ?
Есть ли способ построить предикат для фильтрации по типу класса?Можно ли фильтровать NSArray по классам?
В настоящее время я просматриваю массив и проверяю класс каждого объекта. Может быть, есть более чистый способ?
Вы можете добавить категорию в 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 нет такого метода, поэтому потребность в категории.
Вы также можете сделать self.class.description –
@BrianKing отличная точка –
Вы также можете сравнить классы также в своем предикате.
Но, вероятно, это не сработает, как вы ожидали бы, если вы пытаетесь фильтровать объекты, принадлежащие кластерным классам, или если у вас есть подклассы.
Например, NSDate
, когда экземпляр, как правило, __NSCFDate
и NSString
может быть NSCFString
, а также другие конкретные частные уроки.
Возможно, вам лучше всего пройти через набор и использовать -isKindOfClass:
в качестве теста.
ЕСЛИ вы действительно хотите использовать NSPredicate
, хотя вы можете сделать это. В качестве примера, это будет фильтровать массив для всех объектов, полученных из NSString
. Если вы хотите строгое членство в классе, вы можете заменить isKindOfClass:
на isMemberOfClass:
.
Любой селектор, который реализует все объекты в коллекции, принимает один аргумент и возвращает BOOL
.
NSArray *mixedArray = {...};
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"self isKindOfClass: %@",
[NSString class]];
NSLog(@"%@", [mixedArray filteredArrayUsingPredicate:predicate]);
+1 Я никогда не думал о том, чтобы поставить селектор непосредственно в предикат. Ухоженная! –
Это не упоминается в руководстве по программированию Predicate (что означает, что это делается в строке формата технически недокументировано), но функция настраиваемого селектора резервируется ссылкой: http://developer.apple.com/mac/library/ документация/Cocoa/Reference/Foundation/Classes/NSComparisonPredicate_Class/Reference/NSComparisonPredicate.html # // apple_ref/occ/clm/NSComparisonPredicate/predicateWithLeftExpression: rightExpression: customSelector: Очень круто. –
Да, я изначально написал это длинным путем, но на жаворонке попробовал его в строке формата и был удивлен, увидев, что он работает. –
Начиная с прошивкой 4 и Mac OS 10.6, можно использовать +[NSPredicate predicateWithBlock:]
, а также. Например:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [object isKindOfClass:[NSString class]];
}];
Это позволяет вам выразить свои предикаты исключительно в Objective-C, а не синтаксис предиката требуемого predicateWithFormat:
.
этот заслуживает большего количества голосов –
Почему вы вставляете такие разные объекты в один и тот же массив в первую очередь? –
Одна из причин заключается в том, что у вас есть массив абстрактных классов. У вас могут быть все классы Person, но вы хотите отфильтровать Doctors или Lawyers. – rob5408