UISearchBar Scope Bar Method - iphone

I have a UISearchBar in my app.and I want the four Scope bars in this UISearchBar that I have given from the XIB file .say one , two , three and four and now Problem is I have four array s which contains separates values for each array ..say array one , array two , array three and array four .
Now I want when I search on pressing scope bar one only array one values should search ..
on pressing scope bar two only array twovalues should search and so on ..
Is there any method for scope bar button available to search ?
like If( scope_bar==1){...}else
like If i search for scope barone then it will display only array one. is there any method available ..I searched on the apple documentation but could not get

You should read some tutorials about NSDictionary . i have implemented this search on book search app where titles and authors were searched both at same time.
// for each book
NSDictionary * book = NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
title, #"TITLE", author, #"AUTHOR", nil];
[dataSource addObject:book];
after that in search method you can make changes according to your own ease
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[tableData removeAllObjects];
if(searchText != nil && ![searchText isEqualToString:#""]){
for(NSDictionary * book in dataSource){
NSString * title = [book objectForKey:#"TITLE"];
NSString * author = [book objectForKey:#"AUTHOR"];
NSRange titleRange = [[title lowercaseString] rangeOfString:[searchText lowercaseString]];
NSRange authorRange = [[author lowercaseString] rangeOfString:[searchText lowercaseString]];
if(titleRange.location != NSNotFound || authorRange.location != NSNotFound)
[tableData addObject:book];
}
}
[tableView reloadData];
}

Related

Search bar for searching in article in iOS

Hello there, I'm new iphone developer and I want you guidance…
I want to make an app with legal terms and explanation to different legal articles…
The problem is that I want to have a search bar, so the user is able to search inside the article for any word that he wants…how can this be done???
Thanks
I have array of dictionary and i am searching record like this
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
ProductFilteredArray = [[NSMutableArray alloc] init];
for (NSMutableDictionary * cty in globleAry)
{
NSRange nameRange = [[cty objectForKey:#"Name"] rangeOfString:text options:NSCaseInsensitiveSearch];
if(nameRange.location != NSNotFound)
{
[ProductFilteredArray addObject:cty];
}
}
//copy this array in arrat of table
tableArray = [ProductFilteredArray mutableCopy];
[table reloadData];
}

Search any combination of words or characters using searchDisplay controller in iOS

Hi I have a master array that populates the tableview and I have a filtered array for the search results. Both of these work fine using the below method. My tableview and search display array is working well except for the below issue under this code block.
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
for (product *new in parserData)
{
//Description scope
if ([scope isEqualToString:#"Description"])
{
NSRange result = [new.description rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
if (result.location != NSNotFound)
{
[self.filteredListContent addObject:new];
}
}
//Product scope
if ([scope isEqualToString:#"Product"])
{
NSRange result = [new.item rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
if (result.location != NSNotFound)
{
[self.filteredListContent addObject:new];
}
}
}
}
What I would like to achieve is this. I have an Item in the master array called LMD-2451 TD Professional 3D LCD Monitor. I can search for TD Professional, TD Pro, TD and it returns the correct item mentioned above using any case. However if I search Pro TD it doesn't show any result. The problem I face is the user may not know the order the product title or description might be? So I would need to implement something that would do this logically. I am really stuck with what to do.
For reference
NSMutableArray *parserData; // Complete main full Array
NSMutableArray *filteredListContent; // Array for the Search-results
Any suggestions would be greatly appreciated.
How about using componentsSeperatedByString:#" " on your search string to split it into (in your example) an array of 2 strings, #"Pro" and #"TD". Then loop through the array using the rangeOfString: check that all the components in the array are found in new.item.
//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.item rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
foundSearchText &= (result.location != NSNotFound);
}
// If all search words found, add to the array
if (foundSearchText)
{
[self.filteredListContent addObject: new];
}
}

Suggest # tags while typing (like Twitter) for iPhone UITextView

I'd building an app that uses hashtags, like Twitter or Tweetbot. When you're typing a message, if you type the hashtag symbol, I'd like to suggest tags that match the current one you're typing.
I've already figured out how to get the UITableView to appear and show a list of hashtags, but what I can't figure out is how to do the following:
Get the NSRange of the current word being typed,
See if that range is formatted like a hashtag (NSRegularExpression #"#\\w\\w*")
(From here on out, I've got the code figured out to search for matching hashtags and show them in the UITableView)
Can anyone help me with steps 1 and 2? I've been thinking about using textViewDidChange:, but I'm concerned that the app's performance might suffer if I'm constantly running methods every time the characters change.
Thanks!
I figured it out! I wound up using the textViewDidChange: and textViewDidChangeSelection: methods.
To get the NSRange of the current hashtag being typed, I ran a for loop over the NSRegularExpression matches in the text string. From there, I used NSLocationInRange to find out if the current cursor position intersected any of the hashtags.
Here's the code:
//Get the ranges of current hashtags
NSArray *hashtagRanges = [StringChecker rangesOfHashtagsInString:textView.text];
NSTextCheckingResult *currentHashtag;
if ([hashtagRanges count] >0)
{
//List the ranges of all the hashtags
for (int i = 0; i<[hashtagRanges count]; i++)
{
NSTextCheckingResult *hashtag = [hashtagRanges objectAtIndex:i];
//Check if the currentRange intersects the hashtag
//Have to add an extra space to the range for if you're at the end of a hashtag. (since NSLocationInRange uses a < instead of <=)
NSRange currentlyTypingHashtagRange = NSMakeRange(hashtag.range.location, hashtag.range.length + 1);
if (NSLocationInRange(currentRange.location, currentlyTypingHashtagRange))
{
//If the cursor is over the hashtag, then snag that hashtag for matching purposes.
currentHashtag = hashtag;
}
}
if (currentHashtag){
//If we found one hashtag that we're currently editing
//Display the hashtag suggester, feed it the current hashtag for matching.
[self showTagTable];
//Get the current list of hashtags into an array
NSFetchRequest *hashtagRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *tagEntityDescription = [NSEntityDescription entityForName:#"Tags"
inManagedObjectContext:self.note.managedObjectContext];
[hashtagRequest setEntity:tagEntityDescription];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"dateLastUsed"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[hashtagRequest setSortDescriptors:sortDescriptors];
NSPredicate *tagPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", [noteTextView.text substringWithRange:currentHashtag.range]];
[hashtagRequest setPredicate:tagPredicate];
tagsToDisplay = (NSMutableArray *)[self.note.managedObjectContext executeFetchRequest:hashtagRequest error:nil];
[tagListTable reloadData];
//If there are no matching hashtags, then let's hide the tag table.
if ([tagsToDisplay count] == 0)
{
[self hideTagTable];
return;
}
}
The StringChecker class is a custom one that I wrote, it just has class methods that parse the strings. I made StringChecker a class because the methods are used in several places in the app. Here's the method:
#pragma mark - Hashtag Methods
+(NSArray *)rangesOfHashtagsInString:(NSString *)string {
NSRegularExpression *hashtagDetector = [[NSRegularExpression alloc] initWithPattern:#"#\\w\\w*"
options:NSRegularExpressionCaseInsensitive
error:nil];
NSArray *hashtagRanges = [hashtagDetector matchesInString:string
options:NSMatchingWithoutAnchoringBounds
range:NSMakeRange(0, string.length)];
return hashtagRanges;
}
+(NSUInteger)numberOfHashtagsInString:(NSString *)string {
NSRegularExpression *hashtagDetector = [[NSRegularExpression alloc] initWithPattern:#"#\\w\\w*"
options:NSRegularExpressionCaseInsensitive
error:nil];
NSUInteger numberOfHashtags = [hashtagDetector numberOfMatchesInString:string
options:NSRegularExpressionCaseInsensitive
range:NSMakeRange(0, string.length)];
return numberOfHashtags;
}
Another way I figured out to do this is as follows.
In the - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text function I put a listener for a # being typed which begins recording the characters following the hash until the user types a space at which time it resets.
if ([text isEqualToString:#"#"]) {
recordingHashTag = YES;
startParse = range.location;
}else if ([text isEqualToString:#" "]) {
currentHashTag = nil;
recordingHashTag = NO;
theTable.hidden = YES;
}
if (recordingHashTag == YES) {
NSString *value;
if (startParse > [textView.text length] - startParse) {
value = [textView.text substringWithRange:NSMakeRange(startParse, [textView.text length] - startParse)];
[self filterHashTagTableWithHash:value];
}
}
If the BOOL recordingHashTag is set to YES I pass the substring containing the hashtag text to a function which searches a pre populated array of hashtags. If there is a match it adds that entry to a filtered array of hashtags which it uses to populate the tableview on the fly.
-(void)filterHashTagTableWithHash:(NSString *)hash{
[self.filterHashTagArray removeAllObjects];
for (NSString *hashTag in self.hashTagArray ){
NSRange result = [hashTag rangeOfString:hash options:NSCaseInsensitiveSearch];
if (result.location != NSNotFound) {
[filterHashTagArray addObject:hashTag];
}
}
if (filterHashTagArray.count) {
theTable.hidden = NO;
}else{
theTable.hidden = YES;
}
[self.theTable reloadData];
}
The final step is to insert the hash tag when the user clicks on the entry in the table.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = (UITableViewCell*)[self tableView:theTable cellForRowAtIndexPath:indexPath];
NSString *newString = [textViewComment.text stringByReplacingCharactersInRange:NSMakeRange(startParse, [textViewComment.text length] - startParse) withString:cell.textLabel.text];
textViewComment.text = newString;
}
Just don't forget to clear out your variables when a user backspaces mid hash tag.

Help with Search bar scope buttons

I have a UI that displays data from a user table like FirstName, LastName, Email,etc. Now i want to create a search bar along with scope buttons that filters data depending on the scope button clicked. I have 2 scope buttons, FirstName and LastName. By default FirstName button is selected. Below is how I add my data to a mutablearray,
userData = [[NSMutableArray alloc] init];
for (NSDictionary *tmpDic in response) {
[userData addObject: [NSString stringWithFormat: #"%# %#",
[tmpDic valueForKey: #"FirstName"],[tmpDic valueForKey: #"LastName"]]];
}
My search code,
- (void) searchTableView {
NSString *searchText = theSearchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (NSString *sTemp in userData)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[copyuserData addObject:sTemp];
}
NSLog(#"Copied data is:%#", copyuserData);
[searchArray release];
searchArray = nil;
}
The above code works well for searching the userData array, but i am not sure how will i change the code so that depending on FirstName, LastName scope buttons it will display the result. how i will hook up the buttons to the search bar so that it only display result depending on what scope bar button is clicked. Thanks in advance..
You need to do two things:
1. Look at the value of the searchBar.selectedScopeButtonIndex - this will tell you if you need to search first names or last names.
2. Depending on the scope button, you want to search either the first part of each array item or the second part. There are lots of ways to do this. Probably the easiest is to keep 2 parallel arrays, firstNames and lastNames, which you populate from tmpDic. Then for the actual search, you could either loop through firstNames or lastNames, or do a for(int j=0;j<[firstNames count]; j++) and get [firstNames objectAtIndex:j] and compare that to your temp string. If any string matches, add it to your results array.

How to implement UITableView search functionality

My iPhone application has a UITable View implemented with search functionality in it. The values in the table are grouped into sections from A-Z. Whenever a user tap on particular cell in the table it loads a detail view controller which gives all the values of that particular user. Now my problem is whenever I search some contact and tap on a particular user to check his detail view it always returns a contact starting with letter A. So, my doubt is how to implement this search functionality. Is there a way to get the name of the contact I tapped..Please check this screenshot.. For example if I search some contact starting with letter 'B' and tap on that contact it loads the detail view of a contact starting with letter 'A'. I get all the values from the database. Can you please help me out...
This is the code:
The code I wrote here is in a method:
I am getting all the contacts from database and assigning to an array contacts. Then I am grouping all the contacts according to the alphabets and grouping everything into a dictionary with keys as A-Z and values as name of contacts starting with these letters. Now when I search for a particular contact his name may start with either A ,B or Z..so in the search bar when I search for a particular contact for example a contact starting with letter Z, in this case it gives the details of a person with A. I want this to change so that whenever I tap on a particular contact it should load its details. I am unable to figure out how to do it..
contacts = [[db getContacts:#"Contacts"] componentsSeparatedByString:#","];
[db cleanup];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
NSString *charString;
for (int i=65; i<91; i++) {
charString = [NSString stringWithFormat:#"%c",(char *)i];
[tempArray addObject:charString];
}
[charString release];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for (int i=0; i<[tempArray count]; i++) {
NSMutableArray *contactsByIndex = [[[NSMutableArray alloc] init]autorelease];
NSString *tempChar = [tempArray objectAtIndex:i];
for (int j=0; j<[contacts count]-1; j++)
{
NSString *test = [contacts objectAtIndex:j];
NSString *tempString = [test substringToIndex:1];
if ([tempString isEqualToString:tempChar]) {
[contactsByIndex addObject:[contacts objectAtIndex:j]];
}
}
[dict setObject:contactsByIndex forKey:[tempArray objectAtIndex:i]];
}
self.contactNames = dict;
NSArray *array = [[contactNames allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
self.contactKeys = array;
[dict release];
[tempArray release];
//---display the searchbar---
self.tableView.tableHeaderView = searchBar;
searchBar.autocorrectionType = UITextAutocorrectionTypeYes;
listOfContacts = [[NSMutableArray alloc] init];
for (NSString *key in array)
{
NSArray *contactsArray = [contactNames objectForKey:key];
for (NSString *name in contactsArray) {
[listOfContacts addObject:name];
}
}
- (void) searchContactsTableView {
//---clears the search result---
[searchResult removeAllObjects];
for (NSString *str in listOfContacts) {
NSRange titleResultsRange = [str rangeOfString:searchBar.text options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[searchResult addObject:str];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
NSString *selectedRow=nil;
if (isSearchOn) {
selectedRow=[searchResult objectAtIndex:indexPath.row];
}
DetailViewController *detailViewController;
int section_index=[indexPath indexAtPosition:[indexPath length]-2];
int sugarid_Index = [indexPath indexAtPosition: [indexPath length]-1];
NSString* sectionName=[contactKeys objectAtIndex:section_index];
NSLog(#"%#",sectionName);
//This is a method which gets the details of a particular contact based on the section and the row selected..Contacts is the table name
NSString *getContact=[db getId:#"Contacts" bySection:sectionName andIndex:sugarid_Index];
id=[db getContact:#"Contacts" id:getContact];
// Pass the selected object to the new view controller.
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailViewController.eachContact=contactForSugarId;
[self.navigationController pushViewController:detailViewController animated:YES];
}
When I search for a contact it should search for the name in database and should return its details. Is there a way to do it..please let me know or is there a way to get the name of the cell i.e. the contact name so that I can use that in one of my database methods to retrieve the details of the contact I selected.
Off hand it sounds like you're looking in the wrong array of contacts after the search. You need to have two arrays. One with all the contacts, and one with the filtered contacts. When you search, put all the results in order in the filtered list, and pull the details from that one.
Does this make sense?
If not, try posting a bit of code, and explaining your structure.