I have an array of instances of a class called Contact
, which has, among others, the following properties:
NSArray *mailAddressList // Array of NSString
NSArray *websiteList // Array of NSString
NSArray *tags // Array of instances of Tag class
The class tag has the following properties:
NSString *name;
UIColor *color;
I want to use NSPredicate to search a string in any property of each Contact
. This is the code I have:
if([scope isEqualToString:SCOPE_MAIL] || [scope isEqualToString:SCOPE_WEBSITE])
{
// Search through an array
predicate = [NSPredicate predicateWithFormat:@"ANY SELF.%@ contains[c] %@", scope, textSearch];
}
else if([scope isEqualToString:SCOPE_TAG])
{
// Search another object's property
predicate = [NSPredicate predicateWithFormat:@"SELF.%@.name contains[c] %@", scope, textSearch];
}
else
{
// The rest of the properties are instances of NSString
predicate = [NSPredicate predicateWithFormat:@"SELF.%@ contains[c] %@", scope, textSearch];
}
Everything works fine except for SCOPE_TAG
, it doesn't return any values. I don't think I'm using the predicate correctly.
NOTE: I'm new with NSPredicate so I would like to hear some insights if what I'm doing is not ok
Searching in an array of objects can be done in Javascript using a loop, Array.find() or Array.findIndex() methods. Web Development Updates Javascript
As it is relatively time consuming for the app to parse the format string of the NSPredicate, we should try to reduce creating multiple NSPredicate and reuse similar NSPredicate as much as possible. We can use variable value in NSPredicate denoted by $ sign, and substitute its value by calling withSubstitutionVariables method.
Use indexOf () to search for a primitive or findIndex () to search with a function. Continue your JavaScript learning with iteration methods, accessor methods, and mutator methods. Want to learn more? Join the DigitalOcean Community!
Say for a predicate which select Person that have a name “Asriel” and 50 money : The format is "name == %@ AND money == %i". %@ and %i are the format specifiers, %@ will be substituted with an object (eg: String, date etc), whereas %i will be substituted with an integer.
First of all, if you substitute a keypath you should use %K
as arg.
Further, I think you are missing the ANY
argument in your second query. I think you want a result if any of the tag names contains your textSearch
.
To get a better understanding of how predicates work, have a look at the Apple Documentation
I did a quick test and it is still working fine:
NSMutableArray *arrayContacts = [NSMutableArray array];
{
AMContact *contact = [[AMContact alloc] init];
NSMutableArray *arrayTags = [NSMutableArray array];
{
AMTags *tag = [[AMTags alloc] init];
tag.name = @"Test";
[arrayTags addObject:tag];
}
{
AMTags *tag = [[AMTags alloc] init];
tag.name = @"Te2st2";
[arrayTags addObject:tag];
}
{
AMTags *tag = [[AMTags alloc] init];
tag.name = @"No";
[arrayTags addObject:tag];
}
contact.tags = [arrayTags copy];
[arrayContacts addObject:contact];
}
{
AMContact *contact = [[AMContact alloc] init];
NSMutableArray *arrayTags = [NSMutableArray array];
{
AMTags *tag = [[AMTags alloc] init];
tag.name = @"Test";
[arrayTags addObject:tag];
}
contact.tags = [arrayTags copy];
[arrayContacts addObject:contact];
}
NSPredicate *pred = [NSPredicate predicateWithFormat:@"ANY SELF.%K.name contains[c] %@", @"tags", @"Test"];
NSArray *result = [arrayContacts filteredArrayUsingPredicate:pred];
NSLog(@"%@", result);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With