How to use UISearchBar with tableView that has sections - iphone

Ok so I am working on implementing a UISearchBar on a tableView that has sections. This may be wrong, but to populate the table view the first time, I have an array with lots of entries, and then populate the sections like this:
if(indexPath.section ==0){
[cell.textLabel setText:[tableData objectAtIndex:indexPath.row]];
}else if(indexPath.section ==1){
[cell.textLabel setText:[tableData objectAtIndex:indexPath.row+4]];
}else if(indexPath.section ==2){
[cell.textLabel setText:[tableData objectAtIndex:indexPath.row+8]];
}
Which is far from elegant, but it works. Now I am trying to hookup the UISearchBar, and this is the method that I am running into issues with:
- (void)searchBar:(UISearchBar *)sBar textDidChange:(NSString *)searchText
{
[tableData removeAllObjects];// remove all data that belongs to previous search
if([searchText isEqualToString:#""] || searchText==nil){
[tableView reloadData];
return;
}
NSInteger counter = 0;
for(NSString *name in dataSource)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSRange r = [name rangeOfString:searchText];
if(r.location != NSNotFound)
{
[tableData addObject:name];
}
[pool release];
}
[tableView reloadData];
}
So I am making an array again of entries that fit the search criteria, but then when I am trying to reload my tableView, it gets all bungled up because it is expecting sections. But all I want is the results in just a plain section-less tableView.
How can I implement this UISearchBar with a tableView with sections?
Thanks

set a BOOL when you enter search and adjust your section count accordingly
e.g.
in viewDidLoad
BOOL isSearching = NO;
set to YES when you enter the textDidChange method.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
int t;
if (isSearching) t = 1
else {
t= array.count;
}
return t;
}

You don't need to keep another variable around; just interrogate the tableView argument to see who is asking for the number of sections. For example, suppose your data is available in a fetchedResultsController:
if (tableView == self.searchDisplayDisplayController.searchResultsTableView) {
// your table is the search results table, so just return 1
return 1;
} else {
// your table is your "own" table
return [[self.fetchedResultsController sections] count];
}
I do the same thing in many of my table view delegate and data source methods.

Related

How To Fetch the value Section wise in UItableview?

I am trying to make an app in which i use the Grouped Table view .In that I am creating the sections in which the first letter comes from an array and it is doing perfectly.
the code is below
sections=[[NSMutableArray alloc] init];
for(int i=0;i<[PdfNames count]; i++)
{
NSString *s=[[PdfNames objectAtIndex:i] substringToIndex:1];
NSPredicate *p=[NSPredicate predicateWithFormat:#"letter like '%#'",s];
NSArray *check=[sections filteredArrayUsingPredicate:p];
if([check count]<1)
{
dict=[[[NSMutableDictionary alloc] init] autorelease];
[dict setValue:s forKey:#"letter"];
[sections addObject:dict];
}
}
But now i am not able to get that hoe can i get the names of pdf from array which belongs to their secion Or starts with that alphabet.
You are creating an array sections which is of course empty. You then create an array check based on sections. It will therefore also be empty. [check count] will always be zero. No NSDictionary is going to be created.
Clear?
Try following code its basic logic, I hope you can understand.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(section == 0) {
return 10; // Number of rows in section.
} else if (section == 1) {
return 5;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2; // Let say we have two section.
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
if (indexPath.section == 0) {
// Assign your data
} else if (section == 1) {
// Assign your data
}
}
Similarly you can check for the table section on didSelectRowAtIndexPath: method

uitableView reloadData doesn't work after setting delegate, datasource and file's owner connection

I have googled and done lot of research from my side to find out why the reloadData method on tableview wouldn't work. I checked all the possible solutions like the datasource is set, delegate is set, the tableview is connected to the file's owner.
After all these, when I am trying to reload the tableview, the no. of rows method gets called, but the cell for rowAtIndexPath doesn't get called. Below is the code that I have written. Please let me know, where I am going wrong
- (void)onReservationListSuccess:(NSArray *)rData
{
if ( rData != nil )
{
resList = [[NSArray alloc] initWithArray:rData];
if([resList count] > 0)
{
[self.tripsTableView reloadData];
//[self.tripsTableView beginUpdates];
//[self.tripsTableView reloadSections:[NSIndexSet indexSetWithIndex:0]
// withRowAnimation:UITableViewRowAnimationNone];
//[self.tripsTableView endUpdates];
}
else
{
[tripsTableView reloadData];
[tripsTableView setHidden:YES];
[noTripsLabel setHidden:NO];
}
}
if(fsnNeedsRefresh == YES)
{
[[NSNotificationCenter defaultCenter] postNotificationName:UpdateFSNList object:nil];
fsnNeedsRefresh = NO;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int temp=[resList count];
NSLog(#"The no. of rows are %d", temp);
NSLog(#"Testing Purpose");
NSLog(#"The pnr details of the object is:%#",((TripData *)[resList objectAtIndex:0]).pnrDescription);
return 1;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"The cell for the row at indexpath is getting called");
static NSString *CellIdentifier = #"TripCellIdentifier";
TripCell *cell = (TripCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TripCell" owner:self options:nil];
for(id oneObject in nib)
if([oneObject isKindOfClass:[TripCell class]])
cell = (TripCell *)oneObject;
}
// Set up the cell...
TripData *tripData = (TripData *)[resList objectAtIndex:indexPath.row];
cell.pnrLabel.text = tripData.pnr;
NSLog(#"The cell text is %#",tripData.pnr);
cell.pnrDescriptionLabel.text = tripData.pnrDescription;
NSLog(#"The cell text is %#",tripData.pnrDescription);
cell.pnrTypeLabel.text = tripData.pnrType;
NSLog(#"The cell text is %#",tripData.pnrType);
if(checkInAllowed)
{
cell.checkInButton.tag = indexPath.row;
[cell.checkInButton addTarget:self action:#selector(checkIn:) forControlEvents:UIControlEventTouchUpInside];
}
else
{
[cell.checkInButton setEnabled:NO];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller
TripData *tripData = (TripData *)[resList objectAtIndex:indexPath.row];
NSLog(#"%#", tripData.pnr);
if(tripData != nil)
{
TripOverviewViewController *tripOverviewViewController = [[TripOverviewViewController alloc] initWithTrip:tripData];
[self.navigationController pushViewController:tripOverviewViewController animated:YES];
[tripOverviewViewController release];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
From this part of code I cannot say exactly why it does not work but I'll try to explain how reloadData works.
First, how UITableView works: basically, it's a scrollview. When it is drawn, it checks how many rows it has, then checks their height and from its size and scroll position it decides which rows are currently displayed. Then it asks the delegate to return a UITableViewCell for every displayed row.
When the table is scrolled, it removes the hidden cells from the view hierarchy and adds the cells that have appeared.
And now the tricky part - what does reloadData do? It just removes all the UITableViewCells from the table hierarchy. Nothing more. The actual update is done when the table is drawn for the first time after reloadData.
So, my suggestion is - check that your table is not hidden and check its frame. Also, I see that you are accessing both a property getter self.tripsTableView and an ivar tripsTableView. This is confusing. Do they both return the same?

Hiding UITableViewCell

Is there a way to hide a UITableView cell? I'm looking for some property or method I can invoke on the UITableViewCell returned by a synchronous cellForRowAtIndexPath() to hide it and make it unselectable by the user.
For me using mapping is not easy way, so I decided to use SAS method. But it doesn't work with my custom cell. So, I correct it:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 7 && hide7Row){
UITableViewCell* cell = [cells objectAtIndex:indexPath.row];
cell.hidden = YES;
return 0.0;
}
else if(indexPath.row == 8 && hide8Row){
UITableViewCell* cell = [cells objectAtIndex:indexPath.row];
cell.hidden = YES;
return 0.0;
}
else {
return 44.0;
}
}
Works Fine.
You mean to leave a gap in the table where the cell should be, or just to progress from the one before it straight to the one after it? In the former case, I guess you might try getting the cell's contentView and set its hidden property to YES; otherwise, you'll just have to do a little logic in your -tableView:numberOfRowsInSection: and -tableView:cellForRowAtIndexPath: methods, returning (the number of cells you'd otherwise return - 1) from the first, and, depending on whether the row index is less than or greater than the row you're not including, either (the cell you'd otherwise return) or (the cell at (the row index + 1)), respectively.
(edit, because the explanation was convoluted:)
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
if(section == theSectionWithoutARow)
{
if(shouldRemoveTheRow)
return [theArrayWithTheSectionContents count] - 1;
else
return [theArrayWithTheSectionContents count];
}
// other sections, whatever
}
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// blah blah standard table cell creation
id theCellObject;
if(indexPath.section == theSectionWithoutARow)
{
NSInteger theActualRowToDisplay = indexPath.row;
if(shouldRemoveTheRow && indexPath.row >= theRowIndexToRemove)
{
theActualRowToDisplay = indexPath.row + 1;
}
theCellObject = [theArrayWithTheSectionContents objectAtIndex:theActualRowToDisplay];
}
// now set up the cell with theCellObject
return cell;
}
There is no method to do that on the cellForRowAtIndexPath as far as I am aware.
Noah Witherspoon's method seems to be more or less workable, although it will need to be modified if you want multiple rows to be hidden.
Another way to approach it is to create a "cell map", I don't know if this is more efficient or not, but I've used it and it worked.
Let us say you have an NSArray (or mutable version thereof) of data which is to be shown in your TableView. The array's count property is used as the return value for your numberOfRowsInSection delegate method. This is a somewhat typical approach to my knowledge.
To make it so that only some of the rows are shown, I created a "mapping array", which is an NSMutableArray that contains "pointers" to your actual data array. The map contains integers wrapped in NSNumbers. In its virgin state the map's index 0 has the integer 0 (wrapped in NSNumber), index 1 has integer 1, etc.
The UITableView delegate methods are built so that the map's index count is used for numberOfRowsInSection. In the cellForRowAtIndexPath method, it looks at the appropriate index of the map array, retrieves whatever is wrapped in the NSNumber, and then looks in that index of your actual data array.
The benefit of this dereference is that it becomes extremely easy to add and remove cells from the table. Just add/remove the NSNumber objects from your mapping array. Make sense? Sorry, not at my Mac or I could just put up some code samples.
Oh, and don't forget that you have to call the update method (the exact name escapes me) on your TableView so that it refreshes and the cells hide/unhide.
Had the same problem, and as I wanted to avoid some mapping as mentioned, I just set the cell-size to 0:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger row=[indexPath row];
float ret=0.0;
if( row==3) {
ret=0.0;
}
else {
ret=40.0;
}
return ret;
}
I used Matt's technique to create a mapping to cell data. Here is some code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return computeNumberOfRowsAndMapCellData;
}
// Compute mapToCellData to map the index of the cell to the cell data for the
// cell based on TaskConfig show/hide.
// Return the number of rows in section 1.
- (NSInteger)computeNumberOfRowsAndMapCellData {
if (mapToCellData) {
[mapToCellData release];
}
mapToCellData =[[NSMutableArray alloc] init];
if (cellData) {
[cellData release];
}
cellData = [[NSMutableArray alloc] init];
NSInteger numberOfRows = 12; // maximum number of rows
NSNumber *index = [NSNumber numberWithInt:0];
// If the data is not configured to show, decrement the number of rows in the table.
if ( ! [configManager isShowDateForType:task.case_type severity:task.severity]) {
numberOfRows--;
} else {
// Add a map to the cell data with the row number.
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[df stringFromDate:task.respond_due_date], #"Respond Due", nil];
[cellData addObject:dict];
[mapToCellData addObject:index];
int value = [index intValue];
index = [NSNumber numberWithInt:value + 1];
}
// Check the configuration for the rest of the rows of cell data.
....
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.numberOfLines = 0;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:15];
cell.detailTextLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:14];
}
NSUInteger mapIndex = 0;
// Use the mapToCellData to find cell data based on show/hide in ConfigManager for the data type.
mapIndex = [indexPath row];
NSNumber *cellDataIndex = [mapToCellData objectAtIndex:mapIndex];
NSDictionary *cellDataDict = [cellData objectAtIndex:[cellDataIndex unsignedIntegerValue]];
cell.textLabel.text = = [[cellDataDict allValues] objectAtIndex:0];
cell.detailTextLabel.text = [[cellDataDict allKeys] objectAtIndex:0];

iPhone - UITableView - lost data if i go back

I have a TabBar, NavBar, SearchBar with ScopeBar on my screen. I can search data via a remote server and list the content. So I have a NSMutableArray listContent and a filteredListContent like in the example of Apple (TableSearch - http://developer.apple.com/iphone/library/samplecode/TableSearch/index.html):
Now I added in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
these line:
testDetailViewController *testDetailViewController = [[TestDetailViewController alloc] initWithNibName:#"TestDetailView" bundle:[NSBundle mainBundle]];
testDetailViewController.title = testClass.name;
testDetailViewController.myKey = testClass.keyId;
[[self navigationController] pushViewController:testDetailViewController animated:YES];
[testDetailViewController release];
testDetailViewController = nil;
Because of the NavigationBar, there is a "back" button. If I click this button, the TableView is empty, no matches/hits.
What I have to do, so the content will still be there?
Does anyone know?
Thanks a lot in advance & Best Regards.
Source Code:
#implementation SearchViewController
#synthesize listContent, filteredListContent, savedSearchTerm, savedScopeButtonIndex, searchWasActive;
- (void)viewDidLoad {
// restore search settings if they were saved in didReceiveMemoryWarning.
if (self.savedSearchTerm) {
[self.searchDisplayController setActive:self.searchWasActive];
[self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
[self.searchDisplayController.searchBar setText:savedSearchTerm];
self.savedSearchTerm = nil;
}
}
- (void)viewDidUnload {
// Save the state of the search UI so that it can be restored if the view is re-created.
self.searchWasActive = [self.searchDisplayController isActive];
self.savedSearchTerm = [self.searchDisplayController.searchBar text];
self.savedScopeButtonIndex = [self.searchDisplayController.searchBar selectedScopeButtonIndex];
self.filteredListContent = nil;
}
- (void)dealloc {
[listContent release];
[filteredListContent release];
[super dealloc];
}
- (void)setData {
self.listContent = [NSMutableArray arrayWithCapacity:3];
[self.listContent addObject:[SearchObjects itemWithType:#"AAA" name:#"Test1"]];
[self.listContent addObject:[SearchObjects itemWithType:#"BBB" name:#"Test2"]];
[self.listContent addObject:[SearchObjects itemWithType:#"BBB" name:#"Test3"]];
// create a filtered list
self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.listContent count]];
[self.tableView reloadData];
self.tableView.scrollEnabled = YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//If the requesting table view is the search display controller's table view, return the count of the filtered list, otherwise return the count of the main list.
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [self.filteredListContent count];
} else {
return [self.listContent count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
/* If the requesting table view is the search display controller's table view, configure the cell using the filtered content, otherwise use the main list. */
SearchObjects *searchObject = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
searchObject = [self.filteredListContent objectAtIndex:indexPath.row];
} else {
searchObject = [self.listContent objectAtIndex:indexPath.row];
}
cell.textLabel.text = searchObject.name;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// HERE IS THE SOURCE CODE FOR PUSHING TO THE NEXT VIEW
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
// DO SOME CALCULATIONS… AND THE setData METHOD IS CALLED
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
/* Update the filtered array based on the search text and scope. */
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
/* Search the main list for whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array. */
for (SearchObjects *searchObject in listContent) {
if ([scope isEqualToString:#"All"] || [searchObject.type isEqualToString:scope]) {
NSComparisonResult result = [searchObject.name compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame) {
[self.filteredListContent addObject:searchObject];
}
}
}
}
- (void)filterContentForScope:(NSString*)scope {
/* Update the filtered array based on the search text and scope. */
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
/* Search the main list for whose type matches the scope (if selected); add items that match to the filtered array. */
for (SearchObjects *searchObject in listContent) {
if ([scope isEqualToString:#"All"] || [searchObject.type isEqualToString:scope]) {
[self.filteredListContent addObject:searchObject];
}
}
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForScope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
[self filterContentForScope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
#end
You generally don't have to do anything in this case, the data should remain in place. Is there something which is unloading the data? Do you have a viewWillDisappear function which is unloading your array? Are you doing some of the array setup in viewWillAppear.
Put a log statement at the start of your methods to find out when they are being called, it will give you a clearer picture of what's happening.
It is solved. It was a problem which is not obvious with the given source code.
There was an error in my logic.

iPhone - Problems with UITableView - reload data & no hits

I am using this example of Apple's sample code:
http://developer.apple.com/iPhone/library/samplecode/TableSearch/index.html
In this example the UITableView get a list of content at startup. Clicking in the UISearchBar and typing, the content list will be filtered, also checking on scope of the ScopeBar.
I have to rebuild this kind of "instant search" to a "normal search": At the beginning I do not have data for the TableView. The user should click on the SearchBar, type something, press the button "Search" and a search request will be send to a webserver. The webserver´s response will be put into the TableView and the user can switch the scope to filter the result set. Changing the value of the SearchBar does not filter the result list. Only pressing the "Search" initiate a search request.
I took the example code and rebuild it (source code at the bottom).
But I have two problems with it.
At the initial call of the SearchViewController (with TabBar, SearchBar, ScopeBar, TableView), everything is okay. Thereis an empty TableView. But, clicking in the SearchBar and typing ony one character, there is a message that there are "no hits". How could I avoid that? This message should only appear if an user press "Search" and there are really no matches.
My second problem: Typing "hello" and pressing "Search" the TableView does not list the results. If I click "abort" or on a different scope, the results will be listed. So there must something like a missing "reload"?!
I hope someone could help me.
Thanks a lot in adavence & Best Regards.
My source code:
#implementation SearchViewController
#synthesize listContent, filteredListContent, savedSearchTerm, savedScopeButtonIndex, searchWasActive;
- (void)viewDidLoad {
// restore search settings if they were saved in didReceiveMemoryWarning.
if (self.savedSearchTerm) {
[self.searchDisplayController setActive:self.searchWasActive];
[self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
[self.searchDisplayController.searchBar setText:savedSearchTerm];
self.savedSearchTerm = nil;
}
}
- (void)viewDidUnload {
// Save the state of the search UI so that it can be restored if the view is re-created.
self.searchWasActive = [self.searchDisplayController isActive];
self.savedSearchTerm = [self.searchDisplayController.searchBar text];
self.savedScopeButtonIndex = [self.searchDisplayController.searchBar selectedScopeButtonIndex];
self.filteredListContent = nil;
}
- (void)dealloc {
[listContent release];
[filteredListContent release];
[super dealloc];
}
- (void)setData {
self.listContent = [NSMutableArray arrayWithCapacity:3];
[self.listContent addObject:[SearchObjects itemWithType:#"AAA" name:#"Test1"]];
[self.listContent addObject:[SearchObjects itemWithType:#"BBB" name:#"Test2"]];
[self.listContent addObject:[SearchObjects itemWithType:#"BBB" name:#"Test3"]];
// create a filtered list
self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.listContent count]];
[self.tableView reloadData];
self.tableView.scrollEnabled = YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//If the requesting table view is the search display controller's table view, return the count of the filtered list, otherwise return the count of the main list.
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [self.filteredListContent count];
} else {
return [self.listContent count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
/* If the requesting table view is the search display controller's table view, configure the cell using the filtered content, otherwise use the main list. */
SearchObjects *searchObject = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
searchObject = [self.filteredListContent objectAtIndex:indexPath.row];
} else {
searchObject = [self.listContent objectAtIndex:indexPath.row];
}
cell.textLabel.text = searchObject.name;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// HERE IS THE SOURCE CODE FOR PUSHING TO THE NEXT VIEW
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
// DO SOME CALCULATIONS… AND THE setData METHOD IS CALLED
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
/* Update the filtered array based on the search text and scope. */
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
/* Search the main list for whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array. */
for (SearchObjects *searchObject in listContent) {
if ([scope isEqualToString:#"All"] || [searchObject.type isEqualToString:scope]) {
NSComparisonResult result = [searchObject.name compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame) {
[self.filteredListContent addObject:searchObject];
}
}
}
}
- (void)filterContentForScope:(NSString*)scope {
/* Update the filtered array based on the search text and scope. */
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
/* Search the main list for whose type matches the scope (if selected); add items that match to the filtered array. */
for (SearchObjects *searchObject in listContent) {
if ([scope isEqualToString:#"All"] || [searchObject.type isEqualToString:scope]) {
[self.filteredListContent addObject:searchObject];
}
}
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForScope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
[self filterContentForScope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
#end
For your first problem you should set up a delegate for the search bar and then implement – searchBarSearchButtonClicked: and put your searching code in there. You might also have to implement others such as – searchBarTextDidEndEditing: or – searchBar:textDidChange: and make sure that they do not perform the search.
For your second question, you might want to simply reload the tableView using the delegate again from the – searchBarSearchButtonClicked: to make sure that it happens after you have already searched. You can use [tableView reloadData] to accomplish this.
Problem is solved, see in the comments.