Searching the initial letter of a word using searchBar - iphone

In my app, i have a search bar in my contact list page tableview. now my code searches the list based on any letter even if the search text is at the middle of the firstname or lastname. But i want it to search only from the beginning. For example., the word "sh" should pull only "Shiva", "Sheela", etc., but not "sathish", "suresh" etc., can anyone help me on this?
and my code is
- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchText
{
//---if there is something to search for---
if ([searchText length] > 0)
{
isSearchOn = YES;
canSelectRow = YES;
self.ContactTableview.scrollEnabled = YES;
searchTextValue = searchText;
[searchResult removeAllObjects];
for (NSString *str in ContactArray)
{
NSRange range = [str rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(range.location != NSNotFound)
{
if(range.length > 0)//that is we are checking only the start of the names.
{
[searchResult addObject:str];
}
}
}
}
else
{
//---nothing to search---
isSearchOn = NO;
canSelectRow = NO;
self.ContactTableview.scrollEnabled = YES;
//SearchBar.showsCancelButton = NO;
[TitleBarLabel setText:#"All Contacts"];
}
[ContactTableview reloadData];
}

try with predicates,in below code replace your values.
NSPredicate *p = [NSPredicate predicateWithFormat:#"SELF BEGINSWITH[cd] %#",#"A"];
NSArray *a = [NSArray arrayWithObjects:#"AhfjA ", #"test1", #"Test", #"AntA", nil];
NSArray *b = [a filteredArrayUsingPredicate:p];
NSLog(#"--%#",b);
O/P:-
(
AntA,
AntA
)

Related

Search function in iphone? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
My array is like
{
"Samsung Tab",
"Samsung Note",
"Samsung Galaxy",
"Samsung Galaxy Pro",
"Nokia Lumia",
"Nokia 5130",
"Sony Xperia"
}
Some thing like that. I have text box type GALAXY and click the button. I want to show only Samsung Galaxy , Samsung Galaxy Pro in next list view. Can anyone help me?.
Use predicate to filter an array like below
NSArray *arrayMobiles= [NSArray arrayWithObjects:#"Samsung Tab",#"Samsung Note", #"Samsung Galaxy", #"Samsung Galaxy Pro", #"Nokia Lumia", #"Nokia 5130",#"Nokia 5130",#"Sony Xperia", nil];
NSString *strSearchkey = #"GALAXY";
NSPredicate *containPred = [NSPredicate predicateWithFormat:#"SELF contains[cd] %#", strSearchkey];
NSArray *arrayFilter = [arrayMobiles filteredArrayUsingPredicate:containPred];
NSLog(#"%#",arrayFilter);
//output
"Samsung Galaxy",
"Samsung Galaxy Pro"
Take Two NSMutableArray and add one array to another array in ViewDidLoad method such like,
self.listOfTemArray = [[NSMutableArray alloc] init]; // array no - 1
self.ItemOfMainArray = [[NSMutableArray alloc] initWithObjects:#"YorArrayList", nil]; // array no - 2
[self.listOfTemArray addObjectsFromArray:self.ItemOfMainArray]; // add 2array to 1 array
And Write following delegate Method of UISearchBar
- (BOOL) textFieldDidChange:(UITextField *)textField
{
NSString *name = #"";
NSString *firstLetter = #"";
if (self.listOfTemArray.count > 0)
[self.listOfTemArray removeAllObjects];
if ([searchText length] > 0)
{
for (int i = 0; i < [self.ItemOfMainArray count] ; i = i+1)
{
name = [self.ItemOfMainArray objectAtIndex:i];
if (name.length >= searchText.length)
{
firstLetter = [name substringWithRange:NSMakeRange(0, [searchText length])];
//NSLog(#"%#",firstLetter);
if( [firstLetter caseInsensitiveCompare:searchText] == NSOrderedSame )
{
// strings are equal except for possibly case
[self.listOfTemArray addObject: [self.ItemOfMainArray objectAtIndex:i]];
NSLog(#"=========> %#",self.listOfTemArray);
}
}
}
}
else
{
[self.listOfTemArray addObjectsFromArray:self.ItemOfMainArray ];
}
[self.tblView reloadData];
}
}
Output Show in your Consol.
This code might helpful for you...thanks :)
This may help you
- (void)searchArrayFrom: (NSString *) matchString{
NSString *upString = [matchString uppercaseString];
if (searchArray){[searchArray release];searchArray = nil;}
searchArray = [[NSMutableArray alloc] init];
NSMutableArray *temp = [internalEvents copy];
for (int i=0;i<[temp count];i++)
{
NSString *str = [internalEvents objectAtIndex:i];
// Add everyone when there's nothing to match to
if ([matchString length] == 0)
{
[searchArray addObject:str];
continue;
}
// Add the person if the string matches
NSRange range = [[str uppercaseString] rangeOfString:upString];
if (range.location != NSNotFound) {
[searchArray addObject:str];
}
}
[temp release];
temp = nil;
[tblView reloadData];
}
You can use the below given function :
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring
{
for (int i = 0; i < [yourArray count]; i++)
{
NSString *curString = [[yourArray objectAtIndex:i]lowercaseString];
NSString *searchString = [substring lowercaseString];
if ([curString rangeOfString:curStringSmall].location == NSNotFound)
{
}
else
{
//This means searched text is found in your array. you can store it in new array. Which will give you only the search criteria matched element.
}
}
}
You need to call this function on the click of your search button. Like :
-(void)searchButtonClicked
{
[self searchAutocompleteEntriesWithSubstring:txtSearch.text];
}
you might use the NSPrediction
NSString * SEARCH_KEYWORD = #"s";
NSMutableArray *array =
[NSMutableArray arrayWithObjects:#"Bill", #"Ben", #"Chris", #"Melissa", nil];
NSPredicate *sPredicate =
[NSPredicate predicateWithFormat:#"SELF contains[c] '%#'", SEARCH_KEYWORD];
[array filterUsingPredicate:sPredicate];
// array now contains { #"Chris", #"Melissa" }

Customized autocompletion in UITextView

I want to do the customized autocompletion for UITextView...
For example:
If the user starts to type "Busines" I would like to suggest "Business1", "Business2", , so that the user can select any one of the 2 suggestions or choose to type a new one.
All the custom word suggestion will be in the array...
How can I achieve this ??
Is completionsForPartialWordRange:inString:language: something that I can use.. How can I pass the values in the array???
You can try this code.
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring
{
[autocomplete_array removeAllObjects];
for(int i=0;i<[your_main_array count];i++)
{
NSString *curString = [your_main_array objectAtIndex:i];
curString = [curString lowercaseString];
substring = [substring lowercaseString];
if ([curString rangeOfString:substring].location == NSNotFound)
{}
else
{
[autocomplete_array addObject:curString]
}
}
[autocompletedisplayTableView reloadData];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if( textView == your_TextView)
{
[your_TextView resignFirstResponder];
autocompletedisplayTableView.hidden = NO;
NSString *substring = [NSString stringWithString:your_TextView.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
}
}
your_main_array : will be your original array which you'll load from web service.
autocomplete_array : will be the array you'll get after the searching process is finished.
When user search you'll have to pass autocomplete_array to your UITableView

NSMutableArray search

I have a UISearchBar and I am performing a search on an array and displaying result. The search works perfect for the first letter but the application crashes when I add a letter in search or even when I press backspace. Here is the code I am using:
for (NSString *sTemp in arrCatSearch)
{
NSRange titleResultsRange = [sTemp rangeOfString:strSearch options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[searchArray addObject:[catalog.catalogItems objectAtIndex:i]];
i++;
}
The application crashes in the NSRange line.
I am using NSRange like :
NSRange result = [searchString rangeOfString:searchBar.text options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
in search bar's delegate methods
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
Searching an array for results should be done with the NSPredicate class:
NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#",searchBar.text];
//filter array based on the predicate
searchArray = [arrCatSearch filteredArrayUsingPredicate:filterPredicate];
I think this should give you a better result.
if ([sTemp rangeOfString: strSearch options: NSCaseInsensitiveSearch].location != NSNotFound)
{
if (![searchArray containsObject: [catalog.catalogItems objectAtIndex: i]])
{
[searchArray addObject: [catalog.catalogItems objectAtIndex: i]];
}
}

UITableView / UISearchBar Returns Incorrect Results

I am attempting to implement searching in a UITableView. When searching, it appears that the correct number of results are returned, but I am receiving entries from the original stories array in the results, rather than searchResults. I can see that the searchResults array should be the data source, but haven't been able to figure out after tons of searching quite how to pull it off with an array of NSDictionaries. Any help is appreciated.
- (void)handleSearchForTerm:(NSString *)searchTerm {
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
[array release], array = nil;
}
[[self searchResults] removeAllObjects];
if ([[self savedSearchTerm] length] != 0)
{
for (NSDictionary *currentItem in [self stories])
{
if ([[currentItem objectForKey:#"title"] rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
{
[[self searchResults] addObject:currentItem];
}
}
}
}
[tableView isEqual:self.searchDisplayController.searchResultsTableView] is also another alternative to making and managing your own BOOL isFiltering; variable
use NSPredicate for filtering
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"self.title MATCHES %#",searchTerm];
Suppose that your original array is "originalArray" so to get the filtered array use this make two more global variables
NSArray* filteredArray;
BOOL isFiltering;
Now in search bar delegate method do following
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"self.title MATCHES %#",searchTerm];
filteredArray = [[originalArray filteredArrayUsingPredicate:predicate] retain];
}
Now you need to change l'll bit your table view delegate and data source, .... for all the places where you are using
NSDictionary *currentString = [originalArray objectAtIndex:indexPath.row];
use following
NSDictionary *currentString;
if(isFiltering)
currentString = [originalArray objectAtIndex:indexPath.row];
else
currentString = [filteredArray objectAtIndex:indexPath.row];

Sorting an NSArray like the MPMediaPickerController/iPod Library

I'm developing a custom UIViewController for iPhone that emulates a subset of the MPMediaPickerController for files in my application's local documents directory. In particular, I'm attempting to re-create the Songs tab. I've been successful in creating my new controller, except I can't get the song titles to sort like they do in the iPod Library or the MPMediaPickerController. Here's an example of how the song names need to be sorted:
Awesome Song Title
Cool Song
The Darkest Song Ever
My Song Title
A Really Cool Song
Why Me?
4 Hours Wasted
As you can see, the sorting excludes the leading articles in the song titles and also places songs that begin with a numeric value at the end of the list. Can anyone suggest an efficient sorting function that takes these tules into account?
Since it looks like no one could offer up a solution, I thought I would post the solution I came up with. First, I created a model for my data:
#interface MyModel : NSObject
{
NSString* _value;
NSString* _sortableValue;
}
#property (nonatomic,copy) NSString* value;
- (NSString*)sortableValue;
- (NSString*)comparableString:(NSString*)str;
#end
They key to the model is the comparableString method, which gets used to create the sortableValue. Here's the implementation of the model:
#implementation MyModel
#synthesize value=_value;
-(void)dealloc
{
[_value release];
[_sortableValue release];
[super dealloc];
}
- (void)setValue:(NSString*)value
{
[_value release];
_value = [value copy];
[_sortableValue release];
_sortableTValue = nil;
}
- (NSString*)sortableValue
{
if (_sortableValue == nil)
_sortableValue = [[self comparableString:_value] retain];
return _sortableValue;
}
- (NSString*)comparableString:(NSString*)str
{
if (str == nil)
return nil;
else if ([str length] == 0)
return [NSString stringWithString:str];
NSCharacterSet* numbersSet = [NSCharacterSet decimalDigitCharacterSet];
if ([str rangeOfCharacterFromSet:numbersSet options:0 range:NSMakeRange(0, 1)].location != NSNotFound)
return [NSString stringWithString:str];
NSRange range = NSMakeRange(0, [str length]);
if ([str compare:#"a " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 2)] == NSOrderedSame)
range.location = 2;
else if ([str compare:#"an " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 3)] == NSOrderedSame)
range.location = 3;
else if ([str compare:#"the " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 4)] == NSOrderedSame)
range.location = 4;
range.length -= range.location;
NSCharacterSet* lettersSet = [NSCharacterSet letterCharacterSet];
NSUInteger letterOffset = [str rangeOfCharacterFromSet:lettersSet options:0 range:range].location;
if (letterOffset == NSNotFound)
return [NSString stringWithString:str];
letterOffset -= range.location;
range.location += letterOffset;
range.length -= letterOffset;
return [str substringWithRange:range];
}
#end
In addition to the removing the leading articles from the string, it also removes any leading non-letter characters. I have a song in my iPod library entitled "$ell Your $oul", which ends up in the E section in the MPMediaPickerController. I'm not sure that's what I would have done had I crated the initial sorting algorithm, but I was going to consistency with the MPMediaPickerController, so there you go.
The final piece of the puzzle is the UILocalizedIndexedCollation class. This handy little helper class will help you sort your data to make supplying it to a UITableView via a UITableViewDataSource a piece of cake. Here's a snippet on how to use the UILocalizedIndexedCollation class in conjunction with the model:
// tableData will contain an NSArray for each populated section in the table view
NSMutableDictionary* tableData = [NSMutableDictionary dictionary];
NSMutableArray* myArray = [NSMutableArray array];
// Populate myArray with instances of MyModel
UILocalizedIndexedCollation* indexer = [UILocalizedIndexedCollation currentCollation];
for (MyModel* data in myArray)
{
NSInteger index = [indexer sectionForObject:data collationStringSelector:#selector(sortableValue)];
NSNumber* key = [[NSNumber alloc] initWithInteger:index];
NSMutableArray* array = [tableData objectForKey:key];
if (array == nil)
{
array = [NSMutableArray new]; // Will be released after creating a sorted array in the following section
[tableData setObject:array forKey:key];
}
[array addObject:data];
[key release];
}
[tableData enumerateKeysAndObjectsUsingBlock:^(id key, id array, BOOL* stop)
{
NSMutableArray* sortedArray = [[indexer sortedArrayFromArray:array collationStringSelector:#selector(sortableValue)] mutableCopy];
[tableData setObject:sortedArray forKey:key];
[array release];
}];
One quick note about UILocalizedIndexedCollation (from Apple's documentation):
If the application provides a
Localizable.strings file for the
current language preference, the
indexed-collation object localizes
each string returned by the method
identified by selector.
So make sure you provide a Localizable.strings for each language you want to support, or your table view will only have sections A-Z and #.
It took me a while to work out all of the details on this, so I hope it becomes useful for other people. If you see any ways I can improve this, please let me know!
You may need to consider certain characters with accents as well such as è, é, ò, à, ù, ì.
So I slightly modified your code to incorporate this. Your code is a great contribution to all of us iphone developers
- (NSString*)comparableString:(NSString*)str
{
if (str == nil)
return nil;
else if ([str length] == 0)
return [NSString stringWithString:str];
NSCharacterSet* numbersSet = [NSCharacterSet decimalDigitCharacterSet];
if ([str rangeOfCharacterFromSet:numbersSet options:0 range:NSMakeRange(0, 1)].location != NSNotFound)
return [NSString stringWithString:str];
NSRange range = NSMakeRange(0, [str length]);
if ([str compare:#"a " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 2)] == NSOrderedSame)
range.location = 2;
else if ([str compare:#"an " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 3)] == NSOrderedSame)
range.location = 3;
else if ([str compare:#"the " options:(NSAnchoredSearch|NSCaseInsensitiveSearch) range:NSMakeRange(0, 4)] == NSOrderedSame)
range.location = 4;
range.length -= range.location;
NSCharacterSet* lettersSet = [NSCharacterSet letterCharacterSet];
NSUInteger letterOffset = [str rangeOfCharacterFromSet:lettersSet options:0 range:range].location;
if (letterOffset == NSNotFound)
return [NSString stringWithString:str];
letterOffset -= range.location;
range.location += letterOffset;
range.length -= letterOffset;
//my modification starts here.........
NSString * finalString = [str substringWithRange:range];
NSString * firstCharString = [finalString substringToIndex:1];
NSData * encodedData = [firstCharString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString * encodedString = [[NSString alloc] initWithBytes:[encodedData bytes] length:[encodedData length] encoding:NSASCIIStringEncoding];
if ([encodedString isEqualToString:#"?"]) {
return finalString;
}
NSString * finalProcessedString = [finalString stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:encodedString];
[encodedString release];
return finalProcessedString;
}