I have the following extension method to search in an array:
- (NSArray *)searchItemsForTerm:(NSString *)term;
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", term];
return [[self filteredArrayUsingPredicate:resultPredicate] copy];
}
Sometimes not all my objects in the array have the "name" property. In this case I get an exception.
Is there a way to create this predicate which can ignore any non existing properties?
Thanks!
Something like:
- (NSArray *)searchItemsForTerm:(NSString *)term;
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", term];
NSArray *filteredArray = [self filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
if ([evaluatedObject respondsToSelector:#selector(name)]) {
return [resultPredicate evaluateWithObject:evaluatedObject];
}
return NO;
}]];
return filteredArray;
}
Related
Below is my model class
{"ID":1,"Name":"Area 1","Code":"xyz","StartTime":"09:30","EndTime":"13:40"},
{"ID":2,"Name":"Area 2","Code":"xyz","StartTime":"09:00","EndTime":"13:40"},
{"ID":3,"Name":"Area 3","Code":"xyz","StartTime":"10:30","EndTime":"14:40"},
{"ID":4,"Name":"Area 4","Code":null,"StartTime":"09:30","EndTime":"13:30"}]
I have retrieved model class value in NSMutableArray and displayed on TableView, Now I need to search name from model class, Below is my code, however its not been working.
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSString *searchString = searchController.searchBar.text;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF CONTAINS [cd] %#", searchString];
for (NSString *key in _arrAlreaList) {
NSArray *array = [_arrAlreaList valueForKey:key];
NSArray *tempArray = [array filteredArrayUsingPredicate:predicate];
if (tempArray.count > 0) {
[filteredArray addObjectsFromArray:tempArray];
[self.tblArea reloadData];
}
}
}
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSString *searchString = searchController.searchBar.text;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.Name contains [c] %#", searchString];
NSArray *resultArray = [_arrAlreaList filteredArrayUsingPredicate:predicate];
NSLog(#"Result Array %#",resultArray);
}
Try This !!
I am having UISearchBar above UITableView. Its not filtering the data
Here is my code
- (void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text {
if (text) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", text];
_filteredDataArray = [_dataArray filteredArrayUsingPredicate:predicate];
}
[_tableView reloadData];
}
dataArray is an NSMutableArray and filteredDataArray is an NSArray. I've tried the solutions which are given already but its not working that's why am asked again... What I am doing wrong
TRY THIS CODE FOR SEARCH FILTER:
- (void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text {
if (text) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF CONTAINS[cd] %#", text];
_filteredDataArray = [_dataArray filteredArrayUsingPredicate:predicate];
}
[_tableView reloadData];
}
i guess u need to see this, try this function it works for me, but its in swift 3.0, hope it helps you too.
func searchFromList(searchText:String, mainArray:AnyObject, key:String) -> AnyObject{
var searchArray:[AnyObject]
searchArray = []
if searchText.length > 0 {
if mainArray.count > 0 {
let predicate = NSPredicate(format: "\(key) contains[c] %#", searchText)
searchArray = mainArray.filteredArrayUsingPredicate(predicate)
}
}
return searchArray
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
if ([searchText hasPrefix:#"#"]) {
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"(def contains[c] %#)", searchText];
searchResults = [chengduhua filteredArrayUsingPredicate:resultPredicate];
} else {
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"(head beginswith[c] %#) OR (pro beginswith[c] %#) OR (searchableStringValue beginswith[c] %#)", searchText, searchText, searchText];
searchResults = [chengduhua filteredArrayUsingPredicate:resultPredicate];
}
}
My else is working fine, but any # prefixed searches turn up empty.
Any hints?
Is searchText the right thing I need to be prefixing?!
Here's my search display controller:
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
You might find this fixes it :
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"(def contains[c] '%#')", searchText];
(Note the addition of quotation marks around the %#)
Didn't strip the stupid prefix.
Here's my solution
NSString *prefixToRemove =#"#";
NSString *newString = [searchText copy];
if ([searchText hasPrefix:prefixToRemove])
newString = [searchText substringFromIndex:[prefixToRemove length]];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"(def contains[c] %#)", newString];
This is my array :
<__NSArrayI 0x7ae43cd0>(
Regular,
Ultra
)
I'm searching in array in :
- (void)textFieldDidChange:(UITextField *)textField
{
NSPredicate *pred =[NSPredicate predicateWithFormat:#"name beginswith[c] %#", textField.text];
NSArray *filteredArr = [[[[arryService objectAtIndex:0] valueForKey:#"Category"] filteredArrayUsingPredicate:pred] mutableCopy];
NSLog(#"%#",filteredArr);
}
But it crash #
NSArray *filteredArr = [[[[arryService objectAtIndex:0] valueForKey:#"Category"] filteredArrayUsingPredicate:pred] mutableCopy];
Why it happens ?
I have a tableview with a search bar. I was able to use NSPredicate to search the tableview when I add the items to another array:
for(head in items){
[desc addObject:head.DESC];
[category addObject:head.CATEGORY];
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"self CONTAINS[cd] %#", searchText];
searchResults = [desc filteredArrayUsingPredicate:resultPredicate];
}
Now I want to keep the collection together so that a tableView didSelectRowAtIndexPath will be able to use the category object.
I load my table view like this:
for (int i = 0; i < [items count]; i++){
head = [items objectAtIndex:indexPath.row];
labelName.text = head.DESC;
How can I get my NSPredicate to search the collection for head.DESC?
#pragma mark Search Results
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"self CONTAINS[cd] %#", searchText];
searchResults = [items filteredArrayUsingPredicate:resultPredicate];
}
Currently, I am getting this exception when running the above code.
reason: 'Can't use in/contains operator with collection <Order: 0x7b22e900> (not a collection)'
I think I understand your question. You want to be able to filter your items array (which is a bunch of heads) by the DESC property. How about using blocks?
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [[evaluatedObject DESC] containsString:searchText];
}];
searchResults = [items filteredArrayUsingPredicate:resultPredicate];
}
If your Order object defines DESC as a #property (or is otherwise KVC Compliant), you'll be able to just access it directly. This should work:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"self.DESC CONTAINS[cd] %#", searchText];
searchResults = [items filteredArrayUsingPredicate:resultPredicate];
}
I think it helps you:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"ANY self.DESC CONTAINS[cd] %#", searchText];
searchResults = [items filteredArrayUsingPredicate:resultPredicate];
}