NSPredicate and arrays

安稳与你 提交于 2019-12-10 11:27:55

问题


I've got a short question. I have an NSArray filled with Cars (which inherits from NSObject). Car has the @property NSString *engine (also regarded @synthesize)

Now I want to filter the array using NSPredicate:

predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"(engine like %@)", searchText]];
newArray = [ArrayWithCars filteredArrayUsingPredicate:predicate];

This throws an valueForUndefinedKey error. Is the predicateWithFormat correct?

Thanks for your responses.


回答1:


Here's the real reason why it's not working:

When you build a string using stringWithFormat:, it's going to come up looking like this:

@"engine like searchText"

You then pass it to predicateWithFormat:, which is going to see that both the lefthand side and the righthand side of the comparison are unquoted strings, which means it's going to interpret them as if they were keypaths.

When this code runs, it's going to be doing:

id leftValue = [object valueForKey:@"engine"];
id rightValue = [object valueForKey:@"searchText"];
return (leftValue is like rightValue);

The exception getting thrown is your object complaining that it doesn't have a method named "searchText", which is correct.

Contrast this to if you took out the stringWithFormat: call and just put everything directly into predicateWithFormat::

NSPredicate *p = [NSPredicate predicateWithFormat:@"engine like %@", searchText];

predicateWithFormat: is smart. It sees "aha, a %@ replacement pattern! this means I can pop an argument off the argument list and box it up and use it as-is". That's exactly what it's going to do. It's going to pop the value of searchText off the argument list, box it in an NSExpression, and insert it directly into the parsed expression tree.

What's most interesting here is that the expression it creates will be a constant value expression. This means it's a literal value; not a key path, not a collection, etc. It will be the literal string. Then when your predicate runs, it's going to do:

id leftValue = [object valueForKey:@"engine"];
id rightValue = [rightExpression constantValue];
return (leftValue is like rightValue);

And that is correct, and is also why you should not pass stuff through stringWithFormat: before passing it to predicateWithFormat:.




回答2:


k, I found the mistake.

predicate = [NSPredicate predicateWithFormat:@"engine like *%@*", searchText];

works correct. The ** were missing. Additionally your searchText should be uppercase.

@Josuhua this is no real code, just to visualize my problem




回答3:


First, your code is more verbose than necessary, which always opens you up to the possibility that it's wrong. Try:

predicate = [NSPredicate predicateWithFormat:@"engine like %@", searchText];

Second, "ArrayWithCars" looks like a class name (by convention, classes begin with upper-case). Is it actually a class or an improperly-named local variable (ex: "arrayWithCars" or just "cars")?

Third, what is the exact error? What key is undefined? Don't paraphrase errors when asking others for help - we can't see what you're seeing unless you show us.




回答4:


Try with this link.You may know different ways of using NSPredicate



来源:https://stackoverflow.com/questions/2506836/nspredicate-and-arrays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!