我可以使用NSPredicate作为NSDictionary中的密钥

时间:2013-08-21 05:27:49

标签: objective-c nsdictionary nspredicate nscopying

说我有两个NSPredicate s

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

NSPredicate *pb = [NSPredicate predicateWithBlock:^(BOOL)(id evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isKindOfClass:NSClassFromString(@"TestClass")];
}];

我想要的是,当我将pa放入NSDictionary并将其与其他对象关联时,请说obj,稍后当我使用pb签入字典时我回来了obj

这是怎么回事?

我看到NSPredicate实现NSCopying,所以我希望它可以作为密钥。但我对上面概述的案例不太确定。

3 个答案:

答案 0 :(得分:2)

是的,您可以将任何对象用作键,只要其类实现NSCopying

答案 1 :(得分:2)

NSPredicate 会覆盖 isEqual,但这似乎只在 非常简单的案例:

NSPredicate *pa = [NSPredicate predicateWithFormat:@"foo = 'bar'"];
NSPredicate *pb = [NSPredicate predicateWithFormat:@"foo = 'bar'"];
BOOL b = [pa isEqual:pb]; // --> YES

在这种情况下,您可以使用键pa将对象放入字典中并获取 使用键pb返回对象。

但这根本不适用于基于块的谓词,即使它们引用了 同一块

BOOL (^block)(id evaluatedObject, NSDictionary *bindings) = ^BOOL(id evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isKindOfClass:[NSString class]];
};
NSPredicate *pa = [NSPredicate predicateWithBlock:block];
NSPredicate *pb = [NSPredicate predicateWithBlock:block];
BOOL b = [pa isEqual:pb]; // --> NO

即使这样可行,但在您的情况下需要两个 在谓词中被认为是相等的,但事实并非如此:

BOOL (^block1)(id evaluatedObject, NSDictionary *bindings) = ^BOOL(id evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isKindOfClass:[NSString class]];
};
BOOL (^block2)(id evaluatedObject, NSDictionary *bindings) = ^BOOL(id evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isKindOfClass:NSClassFromString(@"NSString")];
};
BOOL b = [block1 isEqual:block2]; // --> NO

最后,事实证明两个具有相同主体的不相等:

BOOL (^block1)(id evaluatedObject, NSDictionary *bindings) = ^BOOL(id evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isKindOfClass:[NSString class]];
};
BOOL (^block2)(id evaluatedObject, NSDictionary *bindings) = ^BOOL(id evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject isKindOfClass:[NSString class]];
};
BOOL b = [block1 isEqual:block2]; // --> NO

因此,您可以将谓词用作字典中的键,但至少对于基于块的键 谓词这很没用。

答案 2 :(得分:0)

不幸的是,它没有像我预期的那样工作。虽然NSPredicate实现了NSCopying,但谓词可以包含任意块的事实应该很明显,实际上不可能可靠地比较两个NSPredicate

在我的机器上测试,即使用于查询字典的相同谓词实例也不会返回先前的设置值。我的猜测是,当字典获取谓词时,它会复制它,并且因为isEqual:的{​​{1}}的实现可能仅在相等的指针上返回true,原始谓词实例与其副本相比也返回false。