Say I have two 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")];
}];
What I want is that when I put pa
in a NSDictionary
and associate it with another object, say obj
, later when I check in the dictionary using pb
I get back obj
.
Is that how it works?
I see that NSPredicate
implements NSCopying
, so I'm hoping that it works as a key. But I'm not sure about the case I outlined above.
NSPredicate
does override isEqual
, but this seems to be useful only in
very simple cases:
NSPredicate *pa = [NSPredicate predicateWithFormat:@"foo = 'bar'"];
NSPredicate *pb = [NSPredicate predicateWithFormat:@"foo = 'bar'"];
BOOL b = [pa isEqual:pb]; // --> YES
In this case you could put an object into a dictionary using key pa
and get the
object back using key pb
.
But this does not work with block-based predicates at all, even if they reference the same block:
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
And even if that would work, it would require in your case that the two blocks in the predicate are recognized as equal, which is not the case:
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
Finally it turns out that two blocks with the same body are not equal:
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
So you can use a predicates as a key in a dictionary, but at least for block-based predicates this is pretty useless.