UISearchBar issue in displaying search result - ios

In my app I have 3 NSMutableArrays namely empJsonArray searchArray and nameArray
empJsonArray is populated using JSON.
nameArray is populated with valueForKey:#"Name" from empJsonArray and searchArray is initially populated with contents of empJsonArray.
the data is displayed in a UITableView
Now I am using UISearchBar for searching through my UITableView and display the relevant data. UISearchBar is working fine but the problem arises when the search data is displayed.
suppose I have 2 names that contain letter "T" when I search for "T" UITableView display 2 items but form the top of the nameArray (i.e. index 0 and 1) not the items that contain "T".
I am also using NSSortDescriptor.
Here's the code:-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MYCell"];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MYCell"];
}
sorter = [[NSSortDescriptor alloc]initWithKey:#"Name" ascending:YES selector:#selector(caseInsensitiveCompare:)];
sortedArray = [self.empJsonArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]];
cell.textLabel.text = [[sortedArray objectAtIndex:indexPath.row]objectForKey:#"Name"];
nameArray = [[NSMutableArray alloc]initWithArray:[sortedArray valueForKey:#"Name"]];
return cell;
}
Search Method:
- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
if ([searchText length]==0) {
[searchArray removeAllObjects];
[searchArray addObjectsFromArray:nameArray];
}
else {
[searchArray removeAllObjects];
for (NSString *string in nameArray) {
NSRange r = [string rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (r.location != NSNotFound) {
[searchArray addObject:string];
}
}
}
[empTable reloadData];
}
you can see the screenshots here
1.Before search
2.After Search

Problem solved.
Instead of displaying the search result in cell
cell.textLabel.text = [[searchArray objectAtIndex:indexPath.row]
I was displaying
cell.textLabel.text = [[sortedArray objectAtIndex:indexPath.row]objectForKey:#"Name"];

Related

Searching in Array of dictionary and displaying data in table view

I have an array of dictionaries where I what to implement search functionality and display data on tableView cells.
Search works quite fine, I have tested it:
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSString *dictionryKey = #"eViela";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K CONTAINS [cd] %#", dictionryKey, searchText];
NSArray *filteredArray = [self.allItems filteredArrayUsingPredicate:predicate];
NSLog(#"%#", filteredArray);
self.sortedText = filteredArray;
[self.tableView reloadData];
}
Now I need tableView to fill data only for key "eViela" while user is typing info in search bar. As of now I can show only all items as per below code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchCell" forIndexPath:indexPath];
EvielasLibrary *library = [[EvielasLibrary alloc] init];
cell.textLabel.text = [[library.library objectAtIndex:indexPath.row]
return cell;
}
I know that it should be easy but I can't figure it out.
Thanks for help!
You need to get Model from array instead of create new one .
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchCell" forIndexPath:indexPath];
EvielasLibrary *library = [self.sortedText objectAtIndex:indexPath.row]; // assume that self.sortedText is your data source array of tableview
cell.textLabel.text = #"" // populate your string here
return cell;
}
NSMutableArray *arrayForTableView = [[NSMutableArray alloc] init];
NSString *dictionryKey = #"eViela";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",dictionryKey];
NSArray *filteredArray = [self.allItems filteredArrayUsingPredicate:predicate];
for (NSInteger i = 0; i<filteredArray.count; i++){
NSString *matchValue = [NSString stringWithFormat:#"%#",[filteredArray objectAtIndex:i]];
if ([matchValue isEqualToString:dictionryKey]){
[arrayForTableView addObject:matchValue];
}
}
Use arrayForTableView array for your tableview
cell.textLabel.text = [arrayForTableView objectAtIndex:indexPath.row];
Problem is that you not updating numberOfRowsInSection delegate method for sortedArray
You need to check if search bar is active or not. if search bar is active then use sortedText array else if search bar is not active then use library.library array
For check search bar active create a global variable isSearchBarActive And assign it true value in searchBarTextDidBeginEditing delegate function and assign false in searchBarTextDidEndEditing
Add Condition in numberOfRowInSection
if searchBarActive {
return self.sortedText.count
}
else {
return library.library.count
}
Add Condition in cellForRowAtIndexPath like this
if searchBarActive {
cell.textLabel.text = [self.sortedText objectAtIndex:indexPath.row]
}
else {
cell.textLabel.text = [library.library objectAtIndex:indexPath.row]
}

How to get the correct object when using search controller

I am using searchdisplaycontroller,I have a table view above that i have a search bar... the table view displays a list of object names.. for example if i have an json object like
json :{
name: testname;
age:12;
maths:50;
english:56;
science:45;
},
{
// list of similar json objects
}
i have displayed only name in table row using cell.name.text = [json valueforKey :#"name"];
when i dont search anything i can get the whole object when ever user presses the any row by writing
[json objectAtIndex:indexPath.row];
My problem is when i search the table i am not getting the correct object at index... for example i search something in the search bar the it displays rows with relevant objects. when i use the same [json objectAtIndex:indexPath.row]; wrong index objects gets assigned pls help here is my code
-(void)filtercontentForSearchText:(NSString *)searchtext scope:(NSString *)scope{
NSPredicate *resultpredicate=[NSPredicate predicateWithFormat:#"SELF contains [cd] %#",searchtext];
searchList=[[searchDataArray valueForKey:#"SubjectDescription" ] filteredArrayUsingPredicate:resultpredicate];
NSLog(#"searchlist %#",searchList );
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
[self filtercontentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles ] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
//This is didselectrowAtindex code...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"selected");
// if ([numberOfTouchesString isEqualToString:#"One"])
// {
NSArray *selected = [searchDataArray objectAtIndex:indexPath.row];
if (self.delegate && [self.delegate respondsToSelector:#selector(selectedSubject:)])
{
if (tableView == self.searchDisplayController.searchResultsTableView){
if ([self.searchDisplayController isActive]){
NSLog(#"searchlist %#",searchList);
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
id searchResult = [searchList objectAtIndex:indexPath.row];
int indexForResult = [json indexOfObject:searchResult];
NSLog(#"indexpath%d " , indexForResult);
searchAppDelObj.didselectjsondata=[json objectAtIndex:indexPath.row];//storing that json data in AppDelegate object
_serachStr = [searchList objectAtIndex:indexPath.row];
//searchAppDelObj.valuePass=(NSArray *)_serachStr;
NSLog(#" searchAppDelObj.valuePass %#",(NSArray *)_serachStr);
//[self.delegate selectedSubject:self];
}
}
else
{
LearningSearchCell *cell = (LearningSearchCell *)[self.learningSearchTableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.subjectNameLabel.text;
searchAppDelObj.didselectstring=cellText;
searchAppDelObj.didSelectArray=[searchDataArray objectAtIndex:indexPath.row];
NSLog(#"appobjarray %#",searchAppDelObj.didSelectArray);
NSLog(#"AppObj.didselectstring %#",searchAppDelObj.didselectstring);
//searchAppDelObj.valuePass=selected;
//[self.delegate selectedSubject:self];
}
if (-[_comparestr isEqualToString:#"search"]) {
searchAppDelObj.valuePass=(NSArray *)_serachStr;
NSLog(#" searchAppDelObj.valuePass %#",(NSArray *)_serachStr);
[self.delegate selectedSubject:self];
}else{
NSLog(#"AppObj.didselectstring %#",searchAppDelObj.didselectstring);
searchAppDelObj.valuePass=selected;
[self.delegate selectedSubject:self];
}
[self.revealViewController revealToggleAnimated:YES];
}
}
//Here is CellForRowAtindexpath code.........
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"learningSearchCellIdentifier";
LearningSearchCell *cell = [self.learningSearchTableView dequeueReusableCellWithIdentifier:cellIdentifier ];
if ((tableView==self.learningSearchTableView)==YES)
{
cell.subjectNameLabel.text=[[json objectAtIndex:indexPath.row]valueForKey:#"name"];
//subjectString=cell.subjectLabel.text;
cell.teacherNameLabel.text=[[json objectAtIndex:indexPath.row]valueForKey:#"age"];
cell.subjecDataAndSessionLabel.text=[[json objectAtIndex:indexPath.row]valueForKey:#"maths"];
NSNumber *test =[[searchDataArray objectAtIndex:indexPath.row]valueForKey:#"Cohort"];
NSString *myString =[NSString stringWithFormat:#"%#",test];
cell.chorotLabel.text=myString;
}
else if (tableView==self.searchDisplayController.searchResultsTableView) {
cell.subjectNameLabel.text=[searchList objectAtIndex:indexPath.row];
NSLog(#"indexpath %d",indexPath.row);
cell.teacherNameLabel.text=[[json objectAtIndex:indexPath.row]valueForKey:#"age"];
cell.subjecDataAndSessionLabel.text=[[json objectAtIndex:indexPath.row]valueForKey:#"maths"];
NSNumber *test =[[searchDataArray objectAtIndex:indexPath.row]valueForKey:#"english"];
NSString *myString =[NSString stringWithFormat:#"%#",test];
cell.chorotLabel.text=myString;
}
else{
cell.subjectNameLabel.text=[json objectAtIndex:indexPath.row];
}
return cell;
}
hope this will help you
As I understood that you want only those name which set of characters contain in your search bar,
first use NSMutableArray *nameJson to add your all the name from json.
and Use NSArray *nameShowing
_nameShowing = _nameJson;
and reload the tableview
uptill now you have your all your name in your table view , and now you search particular name
2. - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
self.nameShowing = nil;
self.nameShowing = [[NSArray alloc]init];
NSPredicate *filter = [NSPredicate predicateWithFormat:#"SELF contains %#", self.searchbar.text];
self.nameShowing = [self.nameJson filteredArrayUsingPredicate:filter];
if(([self.searchbar.text isEqual:#""]))
{
self.nameShowing = self.nameJson;
}
[self.tblView reloadData];
}

App is crashing when NSMutableArray no Objects in iOS

I have four textfields like textfield1, textfield2, textfield3, textfield4 and one button. When I click on the button I am adding the textfield text to an NSMutableArray and populating in a tableview.
My code is:
- (void)buttonClick
{
NSMutableArray *array =[[NSMutableArray alloc]init];
[array addObject: textfield1.text];
[array addObject: textfield2.text];
[array addObject: textfield3.text];
[array addObject: textfield4.text];
}
Populating in table view using delegate methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text =[array objectAtIndex:indexPath.row];
return cell;
}
The above code is working fine. But when I click on button without entering any data in the textfields, the app is crashing because the array is empty. How to solve this problem?
You can't add nil to an array.
[array addObject:textfield1.text ?: #""];
[array addObject:textfield2.text ?: #""];
[array addObject:textfield3.text ?: #""];
[array addObject:textfield4.text ?: #""];
This makes sure there are four items in the array (possibly empty strings).
Why crashes?
You can't add nil in array. It should have something inside of it.
-(void)buttonClick
{
NSMutableArray *array =[[NSMutableArray alloc]init];
if ([textfield1.text length]>0) {
[array addObject: textfield1.text];
}
if ([textfield2.text length]>0) {
[array addObject: textfield2.text];
}
if ([textfield3.text length]>0) {
[array addObject: textfield3.text];
}
}
Try this
-(void)buttonClick
{
NSMutableArray *array =[[NSMutableArray alloc]init];
if(textfield1.text.length > 0)
[array addObject: textfield1.text];
if(textfield2.text.length > 0)
[array addObject: textfield2.text];
if(textfield3.text.length > 0)
[array addObject: textfield3.text];
if(textfield4.text.length > 0)
[array addObject: textfield4.text];
}
Populating in table view using delegate methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text =[array objectAtIndex:indexPath.row];
return cell;
}
if you have multiple text fields then:
//give tag value of each textfield from 100 to 150 or any any tag (i am considering 50 text fields)
for (int i=100; i<=150; i++) {
// self.view or use ur view on which u r addding textfield
id txtF = [self.view viewWithTag:i];
if([txtF isKindOfClass:[UITextField class]]) {
UITextField *txtField = (UITextField*)txtF;
if(txtField.text.length > 0) {
//Add ur object
}
}
}
you can check the textfields before putting an array wheather it has text or not if yes then put in the array only.
This line in the buttonClick method defined a local array variable:
NSMutableArray *array =[[NSMutableArray alloc]init];
It should be
array =[[NSMutableArray alloc]init];
Which is your instance variable array.

How to add a search bar and search display to an rss feed in a uitableview

I created an RSS reader that parses from a .xml file. The numberOfRowsInSection and cellForRowAtIndexPath look like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.parseResults.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//Check if cell is nil. If it is create a new instance of it
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure titleLabel
cell.textLabel.text = [[self.parseResults objectAtIndex:indexPath.row] objectForKey:#"title"];
cell.textLabel.numberOfLines = 2;
//Configure detailTitleLabel
cell.detailTextLabel.text = [[self.parseResults objectAtIndex:indexPath.row] objectForKey:#"summary"];
cell.detailTextLabel.numberOfLines = 2;
//Set accessoryType
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
//Set font and style
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
return cell;
}
I am trying to create a search bar and search display controller, but am not sure how to search the objectForKey "title" or objectForKey "summary" within the UITableView.
Any help would be greatly appreciated.
If you are trying to search for both title and summary, can you try this in your UISearchBarDelegate method
- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchText
{
if ([searchText length] == 0)
{
[self.tableView reloadData];
return;
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.title contains[cd] %# OR SELF.summary contains[cd] %#", searchText, searchText];
NSArray *filteredArray = [self.parseResults filteredArrayUsingPredicate:predicate];
// TODO: Use this filteredArray to reload data
[self.tableView reloadData];
}
Sample project for your reference - https://github.com/deepthit/TableViewSearch.git

Search in a tableView Cell issue

I am using xcode 5 and want to search a tableView data. I used "Search Bar & Search Display Controller" for "searching", "CustomCell" for "tableCell" and all the data are parsing from a remote server by NSXMLParsing. All data are showing with their corresponding image without any problem but some how my search option doesn't work properly. I do the same code for a single array searsing and it was working. But here it isn't. At the time of searching it is crashed. Here is my code:
-(void)loadData
{
countryParser = [[CountryParser alloc] loadXMLByURL:#"http://www.avowstudio.com/iOS/PartProject/iOS7/XMLParsingWithCustomeCell/XMLFiles/XMLParsingWithCustomCell.xml"];
countryArray = [countryParser countryArray];
displayItems = [[NSMutableArray alloc] initWithArray:countryArray];
[self.countryTableView reloadData];
[activityIndicator stopAnimating];
[self loadArray];
}
-(void) loadArray
{
CountryInfo *currentCountryOne = [[CountryInfo alloc] init];
totalArray = [[NSMutableArray alloc] init];
for (int i=0; i < [countryArray count]; i++)
{
currentCountryOne = [countryArray objectAtIndex:i];
[totalArray addObject:currentCountryOne.countryName];
}
}
-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if ([searchText length] == 0)
{
[displayItems removeAllObjects];
[displayItems addObjectsFromArray:countryArray];
}
else
{
[displayItems removeAllObjects];
displayItems = [[NSMutableArray alloc] init];
for (NSString *string in totalArray)
{
NSRange stringRang = [string rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (stringRang.location != NSNotFound)
{
[displayItems addObject:string];
}
}
}
[self.countryTableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [displayItems count];
}
// This method is kept the "tableRow height" after "done searching"
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
tableView.rowHeight = 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CountryCustomCell *Cell = [self.countryTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!Cell)
{
Cell = [[CountryCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
currentCountry = [displayItems objectAtIndex:indexPath.row];
Cell.ContinentLabel.text = currentCountry.continent;
Cell.CountryNameLabel.text = currentCountry.countryName;
Cell.CapitalLabel.text = currentCountry.capital;
imageQueueCountryFlag = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(imageQueueCountryFlag, ^
{
UIImage *imageCountryFlag = [UIImage imageWithData:[NSData dataWithContentsOfURL: [NSURL URLWithString:[currentCountry countryFlag]]]];
dispatch_async(dispatch_get_main_queue(), ^
{
Cell.CountryFlagImageView.image = imageCountryFlag;
[Cell setNeedsLayout];
});
});
return Cell;
}
I don't want to use two Array in "numberOfRowsInSection" & "cellForRowAtIndexPath" with flag or some thing like that, to avoid more coding. If any one familiar with it please share that here. A lot of thanks in advanced.
I think you are added objects of CountryInfo in the [countryParser countryArray]. In your loadArray method, you just initializing a blank object currentCountryOne and each time the for loop executes, trying to add a blank object's property into totalArray. Please make changes as below:
-(void) loadArray
{
totalArray = countryArray;
}
-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if ([searchText length] == 0)
{
[displayItems removeAllObjects];
[displayItems addObjectsFromArray:countryArray];
}
else
{
[displayItems removeAllObjects];
displayItems = [[NSMutableArray alloc] init];
for (CountryInfo *country in totalArray)
{
NSRange stringRang = [country.countryName rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (stringRang.location != NSNotFound)
{
[displayItems addObject:country];
}
}
}
[self.countryTableView reloadData];
}
Instead of adding string to displayItems add the objects containing information about country.
[displayItems addObject:string];
Here you are adding only the countryName to displayItems but while calling cellForRowAtIndexPath: you are asking for its continent,country name and capital which is not present in the array (displayItems) when you reload table after searching.
Exactly which error did you get when it crashed?
It seems to be that when you add an object to your displayItems array. You just add the string object, not the country object.
Your currentCountry is not a country object just the string.
So, in your code enter:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
When you try to parse, it cannot reach:
continent
countryName
capital
Be careful when you search a detailed object.
when you search you add strings to display items not CountryInfo objects so when cellforrow atindexpath gets called again it has to crash

Resources