NSPredicate isKindOfClass仅适用于[myObject类]而不适用于[MyClass类]

时间:2013-08-22 10:13:28

标签: ios objective-c class nspredicate

为什么[MyClass class]无法在谓词中找到我想要的类的对象而[myObject class]有效?请参阅下面的代码示例我希望能够在一个集合中找到MyClass类型的对象,而无需使用该类的虚假实例。

MyClass* myObject = [[MyClass alloc] init];

这不起作用......

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [MyClass class]];
NSArray* predicateResults = [mySet filteredSetUsingPredicate:predicate].allObjects;

这确实有用......

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [myObject class]];
NSArray* predicateResults = [mySet filteredSetUsingPredicate:predicate].allObjects;

2 个答案:

答案 0 :(得分:14)

这样的谓词
[NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [MyClass class]]

实际上有效。它返回与(记录的)

完全相同的谓词
[NSComparisonPredicate
    predicateWithLeftExpression:[NSExpression expressionForEvaluatedObject]
                rightExpression:[NSExpression expressionForConstantValue:[MyClass class]]
                 customSelector:@selector(isMemberOfClass:)]

您的案例中的问题可能是isMemberOfClass: 比较类相等,因此这不会与作为成员的对象匹配 MyClass的子类。

如果MyClass是类集群且myObject是实例,则可能会发生这种情况 一个具体的子类。例如:

NSString *myString = [[NSString alloc] initWithUTF8String:"hello world"];
Class c1 = [NSString class];   //  NSString
Class c2 = [myString class];   //  __NSCFString

BOOL b1 = [myString isMemberOfClass:c1]; // NO
BOOL b2 = [myString isMemberOfClass:c2]; // YES

在这种情况下,[myObject class][MyClass class]是不同的,这可以解释 为什么一个谓词起作用而另一个谓词不起作用。

以下代码改为使用isKindOfClass:并生成预期结果:

NSArray *array = @[@"123", @456, [NSArray array]];
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"self isKindOfClass: %@", [NSNumber class]];
NSArray* predicateResults = [array filteredArrayUsingPredicate:predicate];
NSLog(@"%@", predicateResults);
//  Output: ( 456 )

答案 1 :(得分:4)

严格来说不是你问题的答案(参见MartinR出色的答案),而是记录predicateWithFormat:方法下的(IMO)的替代方案:

您可以使用predicateWithBlock:创建NSPredicate,如下所示:

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isKindOfClass:[myClass class]];
}];

这应该可以正常工作。