Reputation: 1119
currently i am using this to search through my array of dictionaries (from plist file):
for(NSDictionary *wine in mainArray)
{
NSString *wineName = [wine objectForKey:@"name"];
NSRange range = [wineName rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(range.location != NSNotFound)
[searchArray addObject:wine];
}
In this question I am going to have this plist as an example:
<array>
<dict>
<key>name</key>
<string>Banana One (Yellow)</string>
<key>value</key>
<string>1</string>
</dict>
<dict>
<key>name</key>
<string>Apple Two (White)</string>
<key>value</key>
<string>2</string>
</dict>
<dict>
<key>name</key>
<string>Pineapple Three (Orange)</string>
<key>value</key>
<string>3</string>
</dict>
<dict>
</array>
(Do not care about the value)
Ok, When I'm using the UISearchBar with NSCaseInsensitiveSearch i can simply search through the array (ObjectForKey=@"name")
without think about Case. Good!
for example i can search for:@"banana"
and find the :Banana One (Yellow)
and i can search for:@"two"
and find the :Apple Two (White)
and i can search for:@"banana
one" and find the :Banana One (Yellow)
I can also search for:@"Orange"
and find the :Pineapple Three (Orange)
But only if the search is in right sequence
I can't search for:@"One Banana"
or @"Yellow One"
or @"Yellow Banana"
I would really like to be able to search like this, maybe using keywords?
maybe something like this?:
for(NSDictionary *wine in mainArray)
{
NSArray *myArray = [searchText componentsSeparatedByString:@" "];
NSString *wineName = [wine objectForKey:@"name"];
NSRange range = [wineName rangeOfString:myArray options:NSCaseInsensitiveSearch];
if(range.location != NSNotFound)
[searchArray addObject:wine];
}
I know that this really won't work but I think you know what I mean?
So, How to be able to search for example:@"one banana"
and find :Banana One (Yellow)
Upvotes: 1
Views: 1799
Reputation: 1119
SOLVED
Thanks DevFan for your answer! I needed to edit some things for example SELF to SELF.name to specify the key in my array of dictionaries.
NSArray *searchComoponentsWithEmptyStrings = [searchText componentsSeparatedByString:@" "];
NSMutableArray *searchComoponents = [searchComoponentsWithEmptyStrings mutableCopy];
[searchComoponents removeObject:@""]; //remove empty strings from the array (only works with NSMutableArray)
NSMutableString *format = [NSMutableString stringWithFormat:@"SELF.name CONTAINS[c] '%@'",[NSString stringWithFormat:@"%@",searchComoponents[0]]];
for (int i = 1; i < searchComoponents.count; i++) {
[format appendFormat:@"AND SELF.name CONTAINS[c] '%@'",[NSString stringWithFormat:@"%@",searchComoponents[i]]];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%@",format]];
searchArray = [mainArray filteredArrayUsingPredicate:predicate];
and now I can also search for @"banana " (with space at the end) and still find Banana One (Yellow)
Upvotes: 1
Reputation: 3897
I worked out following solution using NSPredicate
.
NSArray *objects = @[@"Banana One",@"Apple Two"];
NSString *searchString = @"one banana";
NSArray *searchComoponents = [searchString componentsSeparatedByString:@" "];
NSMutableString *format = [NSMutableString stringWithFormat:@"SELF CONTAINS[c] \"%@\"",[NSString stringWithFormat:@"%@",searchComoponents[0]]];
for (int i = 1; i < searchComoponents.count; i++) {
[format appendFormat:@" AND SELF CONTAINS[c] \"%@\"",[NSString stringWithFormat:@"%@",searchComoponents[i]]];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"%@",format]];
NSArray *filtered = [objects filteredArrayUsingPredicate:predicate];
For a short explanation: SELF
is the current object in the array, which should be proofed, CONTAINS
looks, whether the left object contains the right object, and [c]
makes it all caseinsensitive.
So for every keyword in the searchString, you add the condition to the predicateformat, so that at the end, you should have a NSPredicate with this format:
SELF CONTAINS[c] object1 AND SELF CONTAINS[c] object2 ....
The last line creates a filtered array using this NSPredicate. For more information on the predicateFormat look here.
Upvotes: 1
Reputation: 36
Maybe you should split the NSString "Banana One (Yellow)" in an array ("Banana", "One", "(Yellow)") and check if one of those contains to your searchtext.
NSString *searchText = @"One";
NSString *txt = @"Banana One (Yellow)";
NSArray* splitString = [txt componentsSeparatedByString:@" "];
for(int i = 0; i < [splitString count]; i++){
if([[splitString objectAtIndex:i] rangeOfString:searchText].location != NSNotFound) {
return txt;
}
}
Upvotes: 0