iOS - Searching Table View - ios

This is my current search code.
-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope {
[filteredList removeAllObjects];
for(Location *item in list)
{
NSRange result = [item.title rangeOfString:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])];
if(result.location != NSNotFound)
{
[filteredList addObject:item];
}
}
}
How would I change this to match any part of the title and not just the start.
Example:
At the moment if I search for 'Las', 'Las Vegas' will appear in the list, but when I search for 'Vegas' it does not.
I want the search term 'Vegas' to come back with 'Las Vegas'
Thanks,
Ashley

Use rangeOfString:options: instead of rangeOfString:options:range:. It is the range parameter that restricts the search to the beginning of the string.
Or if for some reason you want to use rangeOfString:options:range: then use this as range: NSMakeRange(0, [item.title length])

Related

string comparison with options crashes in iOS9.1 with iPhone6 only and Xcode7

The method crashes in iOS9.1 worked earlier. It is called from
(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
The method is
- (void)filterContentForSearchText:(NSString*)searchText
{
[self.searchResults removeAllObjects]; // First clear the filtered array.
for (NSArray *contactsInSection in self.sections)
{
for (Contact *contact in contactsInSection)
{
NSArray *substringArray = [[contact displayName] componentsSeparatedByString:#", "];
for (NSString *substring in substringArray)
{
NSComparisonResult result = [substring compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame)
{
[self.searchResults addObject:contact];
break;
}
}
}
}
}
The line that crashes is the line with the comparison: [substring compare:searchText.... ];
The problem occurs in iOS9.1 with iPhone6 device. Works with iPhone5!!!
Here is a screenshot from the compiler
The problem is your range
range:NSMakeRange(0, [searchText length])];
is longer than the receiver: searchText = #"Po" is 2-character long, while substring = #"n" is only 1-character long. Therefore the method will raise an exception:
range: The range of the receiver over which to perform the comparison. The range must not exceed the bounds of the receiver.
IMPORTANT
Raises an NSRangeException if range exceeds the bounds of the receiver.
(ref: iOS API reference)
Perhaps you should first check searchText.length <= substring.length?

NSComparisonResult misbehaving

my application is comparing strings of requests sent to a function, like -(void)sendSearchRequest:(NSString *)request sport:(NSString *)sport location:(NSString *)location. I'm setting the request to 'Kevin', the sport to 'Baseball' and the location to 'Wellston'.
Then, I'm comparing it against an object whose request is 'Kevin', sport is 'Basketball', and location is 'Wellston'. The sport should return false, but it isn't. Whats going on?
for (Athlete *athlete in self.athletes) {
NSComparisonResult result = [[athlete name] compare:request options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [request length])];
NSComparisonResult sportCompare = [[athlete sport] compare:sport options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [sport length])];
NSComparisonResult locationCompare = [location compare:self.cityName options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [self.cityName length])];
NSLog(#"Location: %#", location);
NSLog(#"Name: %#", request);
NSLog(#"Sport: %#", sport);
if (result == NSOrderedSame && sportCompare == NSOrderedSame && locationCompare == NSOrderedSame) {
[self.filteredArray addObject:athlete];
}
}
Notes:
* I have to take account for user error. These variables are being passed from a UITextField, so if a user enters 'Wellston, OK' but the object's city is 'Wellston', it won't work
If you want to know whether two strings are the same, why are you using NSComparisonResult? That makes no sense at all. It is for sorting. Just use isEqualToString: - that's what it's for.
Or for more a more sophisticated notion of equality, you can implement an anchored substring search. You can make that case-insensitive and diacritic-insensitive. Thus you can determine whether one string starts with another, for example.

UISearchBar that Searches Entire UITableView Cell

I have a tableview that filters based on a search bar. This works well as long as the search begins with the same characters as the cell text.
I would like to be able to search any part of the cell text, even in the middle. For example. If the cell text is "Jon Bon Jovi" I would like it to still come up if the user types "Bon Jovi" or even just "Jovi" into the search bar.
My current code is below:
for (NSDictionary *item in listItems)
{
if ([scope isEqualToString:#"All"] || [[item objectForKey:#"type"]
isEqualToString:scope] || scope == nil)
{
NSComparisonResult result = [[item objectForKey:#"name"]
compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)
range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame)
{
[filteredListItems addObject:item];
}
}
}
Any help would be awesome. Thank you all!
Instead of using -compare:options:range: (which just sorts your search string relative to your item's name), consider looking at -rangeOfString:options: - that will actually search the entire item name for your search string. You would replace the inner body of your if statement with something like:
NSStringCompareOptions opts = (NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch);
NSRange resultRange = [[item objectForKey:#"name"] rangeOfString:searchText
options:opts];
if (resultRange.location != NSNotFound) {
[filteredListItems addObject:item];
}

find a letter anywhere in an array of strings ios

I have the method below for filtering some results:
Currently it does this:
array: alpha, apple, aries, bravo
type a:
alpha
apple
aries
type l (now al)
alpha
I wanted to do this:
new search:
type p=
alPha
apple
below is the code
thank you kindly in advance
-(void) filterResults:(NSString *)searchText{
NSMutableArray *test = [NSMutableArray arrayWithArray:self.listContent];
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
for (int i=0; i<[test count]; i++) {
NSString *stringResult = [test objectAtIndex:i];
NSComparisonResult result = [stringResult compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame){
[self.filteredListContent addObject:stringResult];
}
}
[self.filteredListContent sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];//sort alphabetically
NSLog(#"filtered results = %#",self.filteredListContent);
}
To find the letter anywhere in your string, replace this:
NSComparisonResult result = [stringResult compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame){
[self.filteredListContent addObject:stringResult];
}
with this:
NSRange range = [stringResult rangeOfString:searchText];
if (range.location != NSNotFound) {
[self.filteredListContent addObject:stringResult];
}
Note that it will have to find all of the characters, in order.
If you want to find any of the characters, then use rangeOfCharacterFromSet:.
Try this one.
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"SELF beginswith '%#'", searchText]];
self.filteredListContent = [self.listContent filteredArrayUsingPredicate:predicate];
Hope this helps you.

Search display controller iOS results disappear then reappear between words

I am searching my products like the below. It works fine however when searching between 2 words the results disappear then reappear once the user has entered the first character of the next word. i.e if I search "td pro" or "pro td" the results are there. If I search like this td(i have a result) td(space) I have NO result td p(I have a result) just to add I need to separate the words by space in componentsSeperatedByString because the user may not search for a product in any particular order. Unless there is a better method?
Here is my code:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
for (XMLStringFile *new in rssOutputData_MutableArray)
{
//Product scope
if ([scope isEqualToString:#"Product"])
{
// Split into search text into separate "words"
NSArray * searchComponents = [searchText componentsSeparatedByString: #" "];
;
BOOL foundSearchText = YES;
// Check each word to see if it was found
for (NSString * searchComponent in searchComponents) {
NSRange result = [new.xmlItem rangeOfString:searchComponent options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
NSRange descriptionRange = [new.xmlDescription rangeOfString:searchComponent options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
foundSearchText &= (result.location != NSNotFound|| descriptionRange.location != NSNotFound);
}
// If all search words found, add to the array
if (foundSearchText)
{
[self.filteredListContent addObject: new];
}
}
}
}
Many thanks
I fixed it with the help of another stack question that someone helped me with.
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
for (XMLStringFile *new in rssOutputData_MutableArray)
{
//Product scope
if ([scope isEqualToString:#"Product"])
{
// Split into search text into separate "words"
NSArray * searchComponents = [searchText componentsSeparatedByString: #" "];
//Before searching trim off the whitespace
searchText = [searchText stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
BOOL foundSearchText = YES;
// Check each word to see if it was found
for (NSString * searchComponent in searchComponents) {
NSRange result = [new.xmlItem rangeOfString:searchComponent options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
NSRange descriptionRange = [new.xmlDescription rangeOfString:searchComponent options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
foundSearchText &= (result.location != NSNotFound|| descriptionRange.location != NSNotFound);
}
// If all search words found, add to the array
if (foundSearchText)
{
[self.filteredListContent addObject: new];
}
}
}
}
The winning line is:
//Before searching trim off the whitespace
searchText = [searchText stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];

Resources