I have a UISearchDisplayController properly connected to the header of a custom UITableView in IB. However, when I search for anything the searchResultsTableView only displays "No Results", and I cannot seem to find where the code is incorrect.
searchResults Property
- (NSMutableArray *)searchResults {
if (!_searchResults) {
_searchResults = [[NSMutableArray alloc] initWithCapacity:self.listingPreviews.count];
}
return _searchResults;
}
Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
NSInteger numberOfRows = 0;
if (tableView == self.tableView) {
numberOfRows = self.listingPreviews.count;
} else {
numberOfRows = self.searchResults.count;
}
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Listing";
ListingPreviewTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[ListingPreviewTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell.
if (tableView == self.tableView) {
cell.listingPreview = [self.listingPreviews objectAtIndex:indexPath.row];
} else {
NSLog([[self.searchResults objectAtIndex:indexPath.row] title]);
cell.listingPreview = [self.searchResults objectAtIndex:indexPath.row];
}
return cell;
}
Search Bar Delegate Method
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSInteger searchTextLength = searchText.length;
for (ListingPreview *listingPreview in self.listingPreviews) {
if ((listingPreview.title.length >= searchTextLength) && ([listingPreview.title rangeOfString:searchText].location != NSNotFound)) {
[self.searchResults addObject:listingPreview];
}
}
}
Just try this instead:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Listing";
ListingPreviewTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell.
if (tableView == self.tableView) {
cell.listingPreview = [self.listingPreviews objectAtIndex:indexPath.row];
} else {
NSLog([[self.searchResults objectAtIndex:indexPath.row] title]);
cell.listingPreview = [self.searchResults objectAtIndex:indexPath.row];
}
return cell;
}
Please note that the change was applied on:
ListingPreviewTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
This way you deque a Cell from your own tableView and not from the one created by UISearchDisplayController.
It seems that nothing in your code forces searchDisplayController to reload it's searchResultTableView.
The standard approach is to set UISearcDisplayController's delegate (note the protocol - UISearchDisplayDelegate) and implement – searchDisplayController:shouldReloadTableForSearchString:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
// perform your search here and update self.searchResults
NSInteger searchStringLength = searchString.length;
for (ListingPreview *listingPreview in self.listingPreviews) {
if ((listingPreview.title.length >= searchStringLength) && ([listingPreview.title rangeOfString:searchString].location != NSNotFound)) {
[self.searchResults addObject:listingPreview];
}
}
// returning YES will force searchResultController to reload search results table view
return YES;
}
Related
In the source code below I am able to change my checkmark object value, but at the time of reload data in cellForRowAtIndexPath method it shows old data:
//TableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
return [self.tableData count];
}
//CellforRowAtIndexpath showing old table data
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Recipe *obj = nil;
obj = self.tableData[indexPath.row];
cell.textLabel.text = obj.name;
NSLog(#"Reload Data %#", obj.checkmark);
if ([obj.checkmark integerValue] == 1)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Recipe *recipe = nil;
recipe = [self.tableData objectAtIndex:indexPath.row];
if ([recipe.checkmark integerValue] == 1)
{
recipe.checkmark=#"0";
}
else
{
//recipe.checkmark=#"1";
for (int i=0; i<[self.tableData count]; i++) {
if (i==indexPath.row) {
recipe.checkmark=#"1";
}
else{
recipe.checkmark=#"0";
}
NSLog(#"PK ! %#", recipe.checkmark);
}
}
//[self.tableData addObject:recipe.checkmark];
[self.myTable reloadData];
[self.myTable reloadData];
}
The good news is normally this issue is in the cell for row logic, but it looks like you have that portion right. I believe the issue is in your cell for row logic because you are not updating tableData correctly. See extra comments below.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Recipe *recipe = nil;
recipe = [self.tableData objectAtIndex:indexPath.row];
if ([recipe.checkmark integerValue] == 1)
{
recipe.checkmark=#"0";
}
else
{
//This only gets called if current checked cell is already checked
for (int i=0; i<[self.tableData count]; i++) {
if (i==indexPath.row) {
recipe.checkmark=#"1";
}
else{
//This is still the recipe for the cell currently selected
recipe.checkmark=#"0";
}
NSLog(#"PK ! %#", recipe.checkmark);
}
}
//[self.tableData addObject:recipe.checkmark];
[self.myTable reloadData];
[self.myTable reloadData];
}
Something like this should fix your issue without changing too much of your code or structure.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Recipe *recipe = [self.tableData objectAtIndex:indexPath.row];
if ([recipe.checkmark integerValue] == 1)
{
recipe.checkmark=#"0";
}
else
{
recipe.checkmark=#"1";
}
//remove all old checkmarks
for (int i=0; i<[self.tableData count]; i++)
{
//Only update recipes that are not in this row
if (i!=indexPath.row)
{
recipe = [self.tableData objectAtIndex:i];
recipe.checkmark=#"0";
}
}
[self.myTable reloadData];
}
Another things to consider is instead of using a string that you are converting to an integer that is acting like a BOOL just change recipe's property checkmark to a BOOL. I hope that helps and good luck.
I have UITableView to show whole bunch of words from array.
I also provide search bar on top of table view so when people type a word in textbox search then my code start filtering data from array.
My result is good but my scroll in tableview is never end even though there is only one row.
My tableview result can scroll down and down without no row.
I don't know what going on with my table view.
My code that I have implement.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if(self.tableView == tableView){
return [self.alphabet count];
}else{
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.tableView == tableView) {
return [[self.vocabularyInfo objectAtIndex:section] count];
}else{
return [self.filteredVocabs count];
}
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [self.alphabet objectAtIndex:section];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
if(self.tableView == tableView){
return self.alphabet;
}else{
return nil;
}
}
// Display cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"CommentTableCell";
//-- try to get a reusable cell --
CommentTableCell *cell = (CommentTableCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//-- create new cell if no reusable cell is available --
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellIdentifier owner:self options:nil];
cell = [nib objectAtIndex:0];
}
VocabularyController *vc;
// Display word from database else display vocabulary when searching
if (tableView != self.searchDisplayController.searchResultsTableView) {
vc = [self.vocabularyInfo[indexPath.section] objectAtIndex:indexPath.row];
}else{
vc = [self.filteredVocabs objectAtIndex:indexPath.row];
}
cell.nameLabel.text = vc.korean;
return cell;
}
// My method that I used for filtering my array to display the result
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
if (searchString.length > 0) {
NSArray *vocabToSearch = self.vocabularyInfo;
if (self.currentSearchString.length > 0 && [searchString rangeOfString:self.currentSearchString].location == 0) {
vocabToSearch = self.filteredVocabs;
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"korean CONTAINS[cd] %#", searchString];
self.filteredVocabs = [vocabToSearch filteredArrayUsingPredicate:predicate];
} else {
self.filteredVocabs = self.vocabularyInfo;
}
self.currentSearchString = searchString;
return YES;
}
Please help me!!
Check your tableview's datasource delegate function.
Maybe more detail about your implementation is helpful.
Please check the value you are returning for the number of rows in the following method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
Question: How do I add disclosure indicator arrow to the cells in my search display controller?
In a TableView you would simply set up a prototype cell but it doesn't seem to be as straight forward for the cells inside a search display controller.
BELOW IS THE TABLE VIEW CODE:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return [dangerousItems count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"DangerousCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [dangerousItems objectAtIndex:indexPath.row];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
[self performSegueWithIdentifier: #"showDangerousItemDetail" sender: self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDangerousItemDetail"]) {
DangerousGoodsDetailViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = nil;
if ([self.searchDisplayController isActive]) {
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
destViewController.dangerousItemName = [searchResults objectAtIndex:indexPath.row];
destViewController.dangerousItemImage = [dangerousImage objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
destViewController.dangerousItemName = [dangerousItems objectAtIndex:indexPath.row];
destViewController.dangerousItemImage = [dangerousImage objectAtIndex:indexPath.row];
}
}
}
UISearchDisplayController has a searchResultsDataSource property, which is a regular UITableViewDataSource. You are responsible for providing its implementation (typically, that's the original view controller to which the search display controller is attached).
The data source must implement tableView:cellForRowAtIndexPath:. This is where you produce cells that represent results of the search. When you create a cell that needs a disclosure indicator, add that indicator in the accessory view before returning the cell from the method.
Hi all freind, please how can I use 2 TableView ,i use this code but my problem is I have the same name for cellule
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (choix==1) {
NSLog(#"%d",choix);
return [mutable3 count];
}
else {
NSLog(#"%d",choix);
return [mutable2 count];
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (choix==1) {
NSLog(#"cc%d",choix);
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [mutable3 objectAtIndex:indexPath.row];
// Configure the cell...
return cell;
}
else {
NSLog(#"vvv%d",choix);
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [mutable2 objectAtIndex:indexPath.row];
// Configure the cell...
return cell;
}
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (choix==1) {
NSLog(#"%d",choix);
langue.text =[mutable3 objectAtIndex:indexPath.row];
langView.hidden=TRUE;
}
else {
NSLog(#"%d",choix);
compain.text =[mutable2 objectAtIndex:indexPath.row];
langView.hidden=TRUE;
}
}
Ok its going to be a simple explanation, hope you understand. If you dont please ask and I will elaborate.
TableView Decleration Example:
UITableView tableView1;
UITableView tableView2;
Each tableview has a variable name which it links to that differs. Because we are working with pointers it allows us to do the following in the delegate methods(All of them, this is only one example)
Delegate Method Example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView== tableView1)
{
return 2;
}
else if(tableView== tableView2) //this if statement is not really needed since if you only have 2 table views the second will automatically fall into the else
{
return 3;
}
else //This else is only needed if you use the second if statement
return 0;
}
And you can use the same approach for all delagate methods
I have an issue in creating a CheckMarkAccessoryView in the UITableView.When i select a row in the table i can get a checked mark for that row,but randomly some other rows in the table also gets the check mark.I want only that cell to get the check mark.How can i do this?I am coding for an exclusive list.The following is the code which i have used.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(tableView==tableView1)
{
return […arraycount1…. ];
}
else
{
return […arraycount2…. ];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
else
{
UIView* subview;
while ((subview = [[[cell contentView] subviews] lastObject]) != nil)
[subview removeFromSuperview];
}
if(tableView == tableView1)
{
cell.textLabel.text=[array1 objectAtIndex:indexPath.row];
}
else //Tableview2
{
cell.textLabel.text=[array2 objectAtIndex:indexPath.row];
}
cell.textLabel.font=[UIFont fontWithName:#"Georgia" size:20];
cell.textLabel.textAlignment=UITextAlignmentLeft;
[cell setSelectedBackgroundView:border];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastindex];
if (oldCell.accessoryType == UITableViewCellAccessoryCheckmark);
{
oldCell.accessoryType = UITableViewCellAccessoryNone;
}
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
if (newCell.accessoryType == UITableViewCellAccessoryNone)
{
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
Kindly correct me where i am going wrong.
Thanks in advance for all the experts.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
for (id algoPath in [tableView indexPathsForVisibleRows])
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:algoPath];
cell.accessoryType = UITableViewCellAccessoryNone;
if(algoPath == indexPath)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
}
i tried different things out, nothing worked properly. now i'm iterating over all indices, setting all Accessories to None, and then the current one to accessoryCheckmark. not the cleanest approach but working.
UITableView reuses cell objects as you scroll the table, so setting the cell to show a checkmark means that it will also have a checkmark when it's reused
You need to store the state of each row in an array separate from the cells (or if you only need one cell at a time checked, just store an index somewhere), and then read from that array and set the appropriate accessoryType in the cellForRowAtIndexPath: method.
(alternatively you could simply disable cell reuse by removing the dequeueReusableCellWithIdentifier: call, but that's bad for performance if you have a long list to scroll)
The two if statement cancel each other, just add else like the following :
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastindex];
if (oldCell.accessoryType == UITableViewCellAccessoryCheckmark)
{
oldCell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
if (newCell.accessoryType == UITableViewCellAccessoryNone)
{
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
I think you are looking for these methods!
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section!=0) {
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}
}
//didDeselect method in table view for removing previous checkmark
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section!=0)
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
}
}