I need to add a search bar for a table view.Table contain "Names" which is actually stored in inside an object called "patient".I have an array of "patient" objects.
So to setup a search bar to search for names.But how to do it using NSPredicate?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* CellId= #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellId] ;
}
cell.accessoryType = UITableViewCellAccessoryNone;
ObjPatient = [allPatientDetails objectAtIndex:indexPath.row];
cell.textLabel.text =[NSString stringWithFormat:#"%# %#",ObjPatient.firstName,ObjPatient.lastName];
return cell;
}
Above is the code to show the names on table.
Any suggestions are welcome , Thanks
To Implement search functionality first take look into below links -
https://developer.apple.com/library/ios/documentation/uikit/reference/UISearchBar_Class/Reference.html
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/Reference/NSPredicate.html
Then make changes in your code as follows -
In your .h file declare array -
NSArray *filteredArray;
In - (void)viewDidLoad method -
filteredArray = allPatientDetails;
Then implement UISearchBar delegate method-
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
NSPredicate *predicate = [NSPredicate
predicateWithFormat:#"SELF.firstName contains[c] %#",
searchText];
NSArray *filteredArray = [allPatientDetails filteredArrayUsingPredicate:predicate];
[tableView reloadData];
}
and make changes in your existing method -
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString* identifier= #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] ;
}
cell.accessoryType = UITableViewCellAccessoryNone;
ObjPatient = [filteredArray objectAtIndex:indexPath.row];
cell.textLabel.text =[NSString stringWithFormat:#"%# %#",ObjPatient.firstName,ObjPatient.lastName];
return cell;
}
well for nspredicate with custom object can be done like this.
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF.firstName contains[c] %#",
searchText];
self.searchedMemberNameResults = [self.listedMembers filteredArrayUsingPredicate:resultPredicate];
firstName is attribute of an object
Below you can find code for searching an item based on the label in the storyboard. It searches dynamically; I've tested this and it's working.
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"job_id contains[c] %#",searchText];
searchResultArray = [responceArray filteredArrayUsingPredicate:resultPredicate];
[jobsTable reloadData];
}
Related
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]
}
I am new in IOS and I am creating a search bar for UITableView. It is working fine when I use an array directly, but when I have an array with a dictionary it's not working.
I have an array of dictionaries:
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableDictionary *person1 = [NSMutableDictionary dictionaryWithDictionary:#{
#"Name" : #"john",
#"Age" : #"10"
}];
NSMutableDictionary *person2 = [NSMutableDictionary dictionaryWithDictionary:#{
#"Name" : #"piter",
#"Age" : #"22"
}];
NSMutableDictionary *person3 = [NSMutableDictionary dictionaryWithDictionary:#{
#"Name" : #"rams",
#"Age" : #"23"
}];
self.person = [[NSMutableArray alloc]initWithObjects:person1,person2,person3 ,nil];
}
I have print those dictionary name on UITableView.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"myCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [[self.personobjectAtIndex:indexPath.row]objectForKey:#"Name"];
return cell;
}
It will give me list of names in UITableView. I used a search bar and I want to search for specific words and have them show on my UITableView, but its not working using this code:
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
if([searchText length] == 0){
self.isfiltered = NO;
}
else{
self.isfiltered = YES;
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[cd] %#",searchText];
filteredList = [self.person filteredArrayUsingPredicate:resultPredicate];
}
[self.mytable reloadData];
}
You need to change your data source array while searching .
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.isfiltered ? filteredList.count : self.person.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *simpleTableIdentifier = #"myCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier]; }
cell.textLabel.text = [[ self.isfiltered ? filteredList : self.person objectAtIndex:indexPath.row]objectForKey:#"Name"]; }
return cell;
}
you need to change 'SELF' -> 'Name'.
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
if([searchText length] == 0){
self.isfiltered = NO;
}
else{
self.isfiltered = YES;
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"Name contains[cd] %#",searchText];
filteredList = [self.person filteredArrayUsingPredicate:resultPredicate];
}
[self.mytable reloadData];
}
Then change in your table array.
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (self.isfiltered)
return filteredList.count;
else
return self.person.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *simpleTableIdentifier = #"myCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier]; }
if (self.isfiltered)
cell.textLabel.text = [[self.isfiltered objectAtIndex:indexPath.row]objectForKey:#"Name"];
else
cell.textLabel.text = [[self.person objectAtIndex:indexPath.row]objectForKey:#"Name"];
return cell;
}
Would you please tell me why my SearchBar doesn´t work in my UITableViewController?
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
NSPredicate *predicate = [NSPredicate
predicateWithFormat:#"SELF.TitleInside contains[c] %#",
searchText];
filteredArray = [HelpList filteredArrayUsingPredicate:predicate];
}
Why
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier =#"Cell";
TableViewCell_Rts *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell){
cell = [[TableViewCell_Rts alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.accessoryType = UITableViewCellAccessoryNone;
CellObject *NewIndex = nil;
if (tableView == self.tableView) {
NewIndex = [HelpList objectAtIndex:indexPath.row];
cell.TitleLabel2.text = NewIndex.TitleInside;
cell.DescriptionLabel2.text = NewIndex.DescriptionInside;
} else {
NewIndex= [filteredArray objectAtIndex:indexPath.row];
cell.TitleLabel2.text = NewIndex.TitleInside;
cell.DescriptionLabel2.text = NewIndex.DescriptionInside;
}
CellObject is a NSObject:
#interface CellObject : NSObject
#property (nonatomic, strong) NSString *ImageInside;
#property (nonatomic, strong) NSString *TitleInside;
#end
When i run the application, my tableview looks populated. Then, when i write inside the search bar, the table doesn´t show the results of the search.
Thanks ¡
I have a problem with my search bar I added in my ViewController.
I am getting the following error:
Assertion failure in -[UISearchResultsTableView _configureCellForDisplay:forIndexPath:], /SourceCache/UIKit/UIKit-2935.137/UITableView.m:6509
2014-04-03 18:08:24.355 MyFood[6405:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
configureCell:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
// ToDos *toDo = [self.fetchedResultsController objectAtIndexPath:indexPath];
if (viewMode==AlphabeticalOrder) {
Inventory *toDo=nil;
if (self.searchDisplayController.isActive) {
toDo = [searchResults objectAtIndex:indexPath.row];
} else {
toDo=[inventoryProducts objectAtIndex:indexPath.row];
}
cell.textLabel.text = toDo.inventoryProductName;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterShortStyle];
NSDate *dt = toDo.expireDate;
NSString *dateAsString = [formatter stringFromDate:dt];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Until: %#", dateAsString];
} else {
Inventory *toDo=nil;
if (self.searchDisplayController.isActive) {
NSDictionary *sectionDict=[searchResults objectAtIndex:indexPath.section];
NSArray *sectionData=[sectionDict objectForKey:#"SECTION_DATA"];
toDo = [sectionData objectAtIndex:indexPath.row];
} else {
NSDictionary *sectionDict=[inventoryProducts objectAtIndex:indexPath.section];
NSArray *sectionData=[sectionDict objectForKey:#"SECTION_DATA"];
toDo=[sectionData objectAtIndex:indexPath.row];
}
cell.textLabel.text = toDo.inventoryProductName;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterShortStyle];
NSDate *dt = toDo.expireDate;
NSString *dateAsString = [formatter stringFromDate:dt];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Until: %#", dateAsString];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell.
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
code search bar:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
if (searchText.length!=0) {
if (viewMode==AlphabeticalOrder) {
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
// [searchResults removeAllObjects];
// [searchResults addObjectsFromArray:[inventoryProducts filteredArrayUsingPredicate:resultPredicate]];
searchResults=[inventoryProducts filteredArrayUsingPredicate:resultPredicate];
} else {
//-section mode
NSMutableArray *newDataArray=[NSMutableArray array];
for (NSMutableDictionary *aSectionDict in inventoryProducts) {
NSArray *sectionData=(NSArray*)[aSectionDict objectForKey:#"SECTION_DATA"];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
NSArray *filteredArray=[sectionData filteredArrayUsingPredicate:resultPredicate];
NSDictionary *sectionDataModified=[NSDictionary dictionaryWithObjectsAndKeys:filteredArray,#"SECTION_DATA",[aSectionDict objectForKey:#"SECTION_TITLE"],#"SECTION_TITLE", nil];
[newDataArray addObject:sectionDataModified];
}
searchResults=[NSArray arrayWithArray:newDataArray];
}
}
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
can anyone help?
Since you have added a search bar, you need to check if the cell is not nil:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// This is added for a Search Bar - otherwise it will crash due to
//'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell.
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
When you're using a UISearchDisplayController, the results are displayed in a separate UITableView that uses your original view controller as the delegate and data source. Since that UITableView isn't set up in your storyboard (it's dynamically created and loaded) it doesn't have access to your prototype cells. I was able to get a similar example to work by using:
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
I'm a little concerned about that since you're asking one tableview to create cells to use in a different table view.
It seems like the better approach will be to not create your cells as prototype cells, but instead create them in and load them from, a separate nib file.
You should also read the documents for UISearchDisplayController as there are several other details of the dataSource and delegate protocols that need to be updated to reflect the fact that there are multiple tableviews in play.
This is telling you that your method: cellForRowAtIndexPath is returning a cell that is nil. Which generates this error.
This line here: UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Will be nill, since you never assign anything to cell, nor do you do anything with it.
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