I wonder if there is any way to search for more than one word using UISearchDisplayController? If I for example want to search for posts containing both "James" AND "London"? Or "James" and "Smith"?
I have searched but not found an answer to this.
This is what I do now, to see if the search term is in either the name or address.
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSMutableArray *searchItemsPredicate = [NSMutableArray array];
NSPredicate *namePredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
[searchItemsPredicate addObject:namePredicate];
NSPredicate *addressPredicate = [NSPredicate predicateWithFormat:#"address contains[c] %#", searchText];
[searchItemsPredicate addObject:addressPredicate];
NSCompoundPredicate *combinedPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:searchItemsPredicate];
searchResults = [_array filteredArrayUsingPredicate:combinedPredicate];
}
A possible solution would be to separate each words.
You can use a NSRegularExpression or use simply componentsSeparatedByString: (to keep it simple).
NSArray *words = [searchText componentsSeparatedByString:#" "];
NSMutableArray *allPredicates = [[NSMutableArray alloc] init];
for (NSString *aWord in words)
{
NSPredicate *addressPred = [NSPredicate predicateWithFormat:#"address contains[c] %#", aWord];
NSPredicate *namePred = [NSPredicate predicateWithFormat:#"name contains[c] %#", aWord];
[allPredicates addObject:addressPred];
[allPredicates addObject:namePred];
}
NSCompoundPredicate *finalPredicate = [[NSCompoundPredicate alloc] initWithType: NSOrPredicateType subPredicates:allPredicates];
searchResults = [_array filteredArrayUsingPredicate: finalPredicate];
You can use a more complexe scheme for your "words limitations" (comma, etc.) to mark delimitations for example:
Searching #"Banana, Apple fruit" could be in fact looking for "words" : #"Banana" and #"Apple fruit", in that case the separator string would be "," (and you may have to trim for white spaces).
Related
I'm trying to write a filter with NSPredicate that states:
IF field_Uid contains 47 and field_Target contains 202...display these items
This portion works great. However, I also want to show items in which the reverse is true, eg.:
OR IF fieldUid contains 202 and fieldTarget contains 47...display these
items also
Right now, I have the following code:
NSString *targetedUser = #"47";
NSString *myID = #"202";
NSPredicate *p1 = [NSPredicate predicateWithFormat:#"fieldUid contains[cd] %#", targetedUser];
NSPredicate *p2 = [NSPredicate predicateWithFormat:#"fieldTarget contains[cd] %#", myID];
//E.G. See p3 & p4 being the reverse?
// NSPredicate *p3 = [NSPredicate predicateWithFormat:#"fieldUid contains[cd] %#", myID];
// NSPredicate *p4 = [NSPredicate predicateWithFormat:#"fieldTarget contains[cd] %#", targetedUser];
NSCompoundPredicate *p = [NSCompoundPredicate andPredicateWithSubpredicates:#[p1, p2/*, p3, p4*/]];
NSArray *filtered = [self.messages filteredArrayUsingPredicate:p];
How would I write in the latter? I'm not sure how to do it without making the statement requiring all 4 lines to be true? (See commented out code - I've left it in so you can see what I mean...)
Just combine two compound "and" predicates using a compound "or" predicate.
You have the first compound "and" predicate in your question. Create the 2nd compound "and" predicate as needed.
Now use [NSCompoundPredicate orPredicateWithSubpredicates:] passing in the two "and" compound predicates.
you can also use
NSString *targetedUser = #"47";
NSString *myID = #"202";
//this will easily fix your issue, simply update your query like this
NSPredicate *p = [NSPredicate predicateWithFormat:#"(fieldUid contains[cd] %# AND fieldTarget contains[cd] %#) OR (fieldUid contains[cd] %# AND fieldTarget contains[cd] %#)", targetedUser, myID, myID, targetedUser];
NSArray *filtered = [self.messages filteredArrayUsingPredicate:p];
I have array of custom objects, _momsArray. shown here is single object of such array:
Custom *yourMom {
name = #"Sally M. Brown";
age = 54;
weight = 43.2;
}
I run my predicate inside searchBar delegate:
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if ([searchText length]<=0) {
_tableDataArr = [[NSMutableArray alloc] initWithArray:_momsArray];
} else{
// filtered _tableDataArr
NSString *filter = #"name BEGINSWITH[cd] %#";
NSPredicate* predicate = [NSPredicate predicateWithFormat:filter, searchText];
NSArray *filteredArr = [_momsArray filteredArrayUsingPredicate:predicate];
_tableDataArr = [[NSMutableArray alloc] initWithArray:filteredArr];
}
[_momTable reloadData];
}
This doesn't give expected result. For example, when I type S, sally doesn't appear at all. What is wrong with my code?
EDIT: The string in the custom objects contains punctuations and therefore it is not the same as other answers.
To filter an array with custom objects you can use this code.
NSString *str = #"text";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.name contains[c] %#", str];
NSArray *arrFiltered = [self.arrDataObject filteredArrayUsingPredicate:predicate];
Hope, it helps.
Your string is not properly generated so use below code :
NSPredicate *predicate = [ NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", text];
arrFilterData = [NSArray arrayWithArray:[arrDataList filteredArrayUsingPredicate:predicate]];
OUTPUT
Before search
After search
And with code
NSPredicate *predicate = [ NSPredicate predicateWithFormat:#"SELF CONTAINS[c] %#", text];
arrFilterData = [NSArray arrayWithArray:[arrDataList filteredArrayUsingPredicate:predicate]];
OutPut:
Edit
Output :
Use this code :
NSPredicate *pred = [NSPredicate predicateWithFormat:#"name CONTAINS[cd] %#", searchText];
NSMutableArray *filteredArr = [[_momsArray filteredArrayUsingPredicate:pred]mutableCopy];
I am try to search word which contain "EVBAR02". Can any body help me in this case. Here is Array Directory.
Here is code.
`NSMutableArray *filteredListContent = [NSMutableArray arrayWithArray:arrayGallery];
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"imageUrl CONTAINS[cd] EVBAR02"];
[filteredListContent filterUsingPredicate:predicate];`
arrayGallery = (
{
imageId = "04";
imageUrl = "/article/THEV-EVBAR04.jpg";
},
{
imageId = "02";
imageUrl = "/article/THEV-EVBAR02.jpg";
},
{
imageId = "06";
imageUrl = "/article/THEV-EVBAR06.jpg";
}
)
But Its not working. What to do?
The ...WithFormat part of predicateWithFormat: works the same way like stringWithFormat:
NSString *searchString = #"EVBAR02";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"imageUrl CONTAINS[cd] %#", searchString];
Or literally in single quotes:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"imageUrl CONTAINS[cd] 'EVBAR02'"];
The quotation is required as described in the documentation:
String constants must be quoted within the expression—single and
double quotes are both acceptable, but must be paired appropriately
(that is, a double quote (") does not match a single quote ('))
Vadian is right.
And if you want to pass the field name as a parameter, use %Kin place of %#:
NSString *searchField = #"imageUrl";
NSString *searchString = #"EVBAR02";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K CONTAINS[cd] %#", searchField, searchString];
You have to set single quotes in your search string :
NSPredicate *predicate = [NSPredicate predicateWithFormat : #"imageUrl CONTAINS[cd] 'EVBAR02' "]
NSString *myString = #"EVBAR02";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"imageUrl
contains[cd] %#", myString];
NSMutableArray *arrResult =[filteredListContent filteredArrayUsingPredicate:predicate];
There is no need of NSString stringWithFormat, directly use NSPredicate predicateWithFormat as below:
NSMutableArray *filteredListContent = [NSMutableArray arrayWithArray:arrayGallery];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"imageUrl CONTAINS[cd] 'EVBAR02'"];
[filteredListContent filterUsingPredicate:predicate];
Hope it will help:)
Here is my test for filtering the array by a string. It work well if my string doesn't contain (') character
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"b'en", #"Adam", #"Melissa", #"arbind", nil];
//NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b'"]; -> it work
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b''"]; -> it crash
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"beginwithB = %#",beginWithB);
I also try to change my string to 'b\'' or 'b''' but it still crash
Here is the crash log
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "SELF contains[c] 'b'''"'
How to resolve it? Any help would be great appreciated.
Please try to filter result as follows:
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"b'en", #"Adam", #"Melissa", #"arbind", nil];
NSString *strToBeSearched = #"b'";
//NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b'"]; -> it work
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",strToBeSearched]; //-> it also work
//OR
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b\\''"];
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"containB = %#",beginWithB);
try this
NSString *searchword = #"b";
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",searchword];
you get output of
You were pretty close when you tried backslash. This is the character that NSPredicate uses to escape special characters. However, you need two, not one, backslash:
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"b'en", #"Adam", #"Melissa", #"arbind", nil];
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b\\''"];
// ^^
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"beginwithB = %#",beginWithB);
The reason you need two is Objective-C compiler. It processes all string literals in your code, and replaces escape sequences it encounters. If you would like NSPredicate to see a single backslash, your string literal needs to have two backslashes, because backslash itself is encoded as \\ in Objective-C string literals.
If your name is b'en then,
NSString *name = #"b'en";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == \"%#\"", name];
Hope this will help :)
Currently trying to setup a search would search an Array (bakeryProductArray) which looks like this
"Tea Loaf",
Tiramusu,
"Treacle Loaf",
Trifle,
"Triple Chocolate Brownie",
Truffles,
"Various sponges",
"Viennese Whirls",
"Wedding Cakes"
with what the users types into the UISearchbar. I am unclear on how to represent each item in the array in the CFString.
The code I currently have is.
-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope
{
searchSearch = [NSPredicate predicateWithFormat:#"self CONTAINS[cd]",searchText];
//#"%K CONTAINS[cd] %#"
searchResults = [bakeryProductArray filteredArrayUsingPredicate:searchSearch];
NSLog(#"Filtered Food Product Count --> %d",[searchResults count]);
}
Can answer any questions and supply more code if needed.
Is this what your are looking for?
NSArray *bakeryProductArray = #[#"Tea Loaf", #"Tiramusu", #"Treacle Loaf", #"Trifle"];
NSString *searchText = #"tr";
NSPredicate *searchSearch = [NSPredicate predicateWithFormat:#"self CONTAINS[cd] %#", searchText];
NSArray *searchResults = [bakeryProductArray filteredArrayUsingPredicate:searchSearch];
NSLog(#"%#", searchResults);
// "Treacle Loaf",
// Trifle
This finds all strings that contain the given search string (case insensitive).
Alternatively, you can use "=" or "BEGINSWITH", depending on your needs.
(More information about predicates in the "Predicate Programming Guide" .)