2

说我有NSPredicate两个

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输入 aNSDictionary并将其与另一个对象相关联时,例如,稍后当我使用I get backobj在字典中检查时。pbobj

它是这样工作的吗?

我看到了NSPredicateimplements NSCopying,所以我希望它可以作为一个键。但我不确定我上面概述的情况。

4

3 回答 3

2

是的,您可以使用任何对象作为键,只要它的类实现NSCopying.

于 2013-08-21T05:34:57.967 回答
2

NSPredicate 确实 override isEqual,但这似乎仅在非常简单的情况下才有用:

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

在这种情况下,您可以使用 key 将对象放入字典中pa并使用 key 取回对象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

因此,您可以使用谓词作为字典中的键,但至少对于基于块的谓词来说,这是非常无用的。

于 2013-08-21T06:08:45.177 回答
0

Unfortunately it doesn't work as I expected. Although NSPredicate implements NSCopying, the fact that a predicate can contain an arbitrary block should make it obvious that it would be virtually impossible to compare two NSPredicates reliably.

Tested on my machine, even the same predicate instance used to query the dictionary won't return the previous set value. My guess is that when the dictionary takes the predicate it copies it, and because the implementation of isEqual: for NSPredicate probably only returns true on equal pointers the original predicate instance compared to the its copy also returns false.

于 2013-08-21T06:08:12.507 回答