Wednesday, February 24, 2010

UITableView How-To: Part 2 - Search

This post has been moved: click here

42 comments:

Steven Sawyer said...

Hi, i was hoping perhaps you could help me debug a little bit of the code you supplied.

The error is coming from this line:


- (void)handleSearchForTerm:(NSString *)searchTerm

{
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
[array release], array = nil;
}
[[self searchResults] removeAllObjects];
if ([[self savedSearchTerm] length] != 0)
{
for (NSString *currentString in [self items])
{
if ([currentString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound) //Error
{
[[self searchResults] addObject:currentString];
}
}
}

}


XCode's debugger says currentString is not a valid CFString and the app crashes.

I'm new to XCode (and programming in general) so maybe you can point me in the right direction.

Thank you!

The Slick One said...

Well, yours is called "items" and mine is called "contentsList", so what else did you change?

Steven Sawyer said...

The only thing i changed in your code was the "items" as you mentioned because my list is coming from an XML i'm parsing using NSXML and it was easier to change it in the new code instead of changing the existing code. Everything else is exactly as your posted code.

The app crashes as soon as i enter a character in the search field, but otherwise works perfectly.

The Slick One said...

My money is on a memory issue in your parser. The problem is not in my code.

Giorgio said...

Hi Brian!
First of all NICE TUTORIAL!!

I followed ur code but when I run the app the Search Bar does not appear (even if I scroll up).

Do u have any idea why this happens?!

The Slick One said...

You made a mistake somewhere. Start over and carefully follow step by step.

Giorgio said...

I tried creating an empty table view controller using the pre-made template offered by xCode.
Then I added the Search Dispaly Controller with the IB!
I run the app and the searchBar does not show anyway!
So which is the explicit part of the code that is necessary to show the searchBar?!?

THANKS!!!

The Slick One said...

You are not following this tutorial at all. So why are you asking questions about the tutorial? Either do what the tutorial says, or go elsewhere to ask questions.

Anonymous said...

Many thanks!!! Works like a charm for my project (only a few small tweaks for my specifics)

Anonymous said...

Thanks very much! Just what I was looking for

Anonymous said...

Great tutorial. Well written step by step instructions.

It works fine for me on the iPhone Simulator but crashes when I attempt to type in the Search field (in simulator). Any idea why? Hopefully you have something a bit more pinpoint than "You made a mistake somewhere. Start over and carefully follow step by step." lol

Thanks for your tutorial and help.

Brian Slick said...

Well, if you're like the last guy who wanted a better answer while providing no more information, then you are using an XML parser that you found elsewhere that has memory management problems. Yet for some reason you've chosen to blame my code for the problem.

DenizD said...

Hi,

Everything seems to be working and when I search I get the correct results, but when I select a result it doesn't pus to the new view. For example in my normal table Art * Phorography is the first object. When I search for geography and select geography it pushes the art & photography view. I know it something to do with didSelectRowArIndexPath method but I don't know how to work around it. Any help would be appreciated thank you.

DenizD said...

Also the link to the sample project code is not working can you sort out the link please??????

Brian Slick said...

Link fixed.

You do the same thing in didSelectRow that you do in cellForRow. It sounds like you are still pulling from the full array, not the search results array.

DenizD said...

Thanks for the reply i did the same thing for didSelectRowAtIndexPAth method but it's still pulling information from the origina array(table). This is my code can you have a look please...

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *contentForThisRow = nil;

if (tableView == [[self searchDisplayController] searchResultsTableView])
contentForThisRow = [[self searchResults] objectAtIndex:indexPath.row];
else
contentForThisRow = [[self courseArray] objectAtIndex:indexPath.row];

[tableView deselectRowAtIndexPath:indexPath animated:YES];

if([[courseArray objectAtIndex:indexPath.row] isEqual:@"Art & Photography"])
{
artPhotographyModule = [[ArtPhotographyModule alloc] initWithNibName: @"ArtPhotography" bundle:nil];
[self.navigationController pushViewController:artPhotographyModule animated:YES];
[artPhotographyModule release];
}

if([[courseArray objectAtIndex:indexPath.row] isEqual:@"Building & Construction"])
{
buildingconstructionModule = [[BuildingConstructionModule alloc] initWithNibName: @"BuildingConstructionModule" bundle:nil];
[self.navigationController pushViewController:buildingconstructionModule animated:YES];
[buildingconstructionModule release];
}
}

Brian Slick said...

Pay attention to your code. Both of your isEqual: lines are comparing to courseArray. You already have this information in contentForThisRow, so there is no reason to go back to the (wrong) array.

And use isEqualToString:

DenizD said...

I don't get it. I'm new to objective-C and im learning it through youtube videos so my knowledge is very very limited on the language. What exactly do you mean can you edit my code to the way it should because I can't fix it myself and im completely stuck. sorry for bothering you.

Brian Slick said...

if([contentForThisRow isEqualToString:@"Art & Photography"])

DenizD said...

I fixed it thanks for your help appreciate it a lot. Great tutorial.

benclayton said...

This tutorial is excellent! Thanks so much - it all worked perfectly for me and saved me hours of pain.

Anonymous said...

Thanks great tutorial! Easy to understand!

Vishnu Unnikrishnan said...

thankks!

Anonymous said...

For my purposes (I have an xml file) I added this:

for (NSDictionary *dictionary in userArrayData)
{
NSString *text1 = [dictionary valueForKey:@"client"];
[searchArray addObject:text1];
}

Thank you very much for the tutorial.

Louis said...

Thank you for your code~
Would you plz tell me what is setSearchResults:?
After I plug your code in my project, it have a warning for it!
warning: 'NPB_list' may not respond to '-setSearchResults:'

when I run the program, after I key in the word on search bar. The APPS off. In the console


*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NPB_list setSearchResults:]: unrecognized selector sent to instance 0x57ad9e0'

Brian Slick said...

Carefully reread the tutorial, and look at the sample project. This is seriously basic stuff here.

Louis said...

Thank for you code!!
But I have a problem. I custom the table cell, but the search result can't be use the height I set in tableView.

I tried to set the cell height in your project. Also have same problem.

Would you plz tell me how can solve this problem?

Brian Slick said...

How did you change it for the main table view? Do that for the search table.

Louis said...

Sorry, Brian.
I really can't found where I can edit the search table height in the project.
Would you plz tell me about it?

Thank you very much about your help!! and thank you again about your great tutorials!!

Brian Slick said...

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
[[controller searchResultsTableView] setRowHeight:[[self mainTableView] rowHeight]];
}

Nothing says "thanks" like hitting the Donate button above.

timmy said...

how do u add a search bar using

sqlite as the database?

its really confusing, im new to programming and im having a hard time implementing it.

im trying to implement it into a navigation based template app, thats using sqlite as the database/data source.

i used what uve put on the website, i got the searchbar to show up, but all the contents in the table view are now gone.

i want the contents to show up, regardless, till you actually search stuff.

Brian Slick said...

I can't help with sqlite. If you're new to programming, you shouldn't be messing with it either. Start simpler.

Guru said...

Hi

Your article is fantastic and too the point. Im sure you have lots of questions and you answered them as well...but I still have my 0.01 cent question..

in your code you mention

// Restore search term

in ViewDidLoad.

Can you please describe its use?

I added new view which Im displaying after
1) Use SearchTerm
2) hit the cell which is filtered which calls "didSelectRowAtIndexPath" there I open new view using presentModalViewController function on self.
3) I display the results (which i pass using property) on UITextField
4) then hit back button on new view to come back to my searchtableview controller (your code)

Here i see the searchTerm is displayed with searchBar highlighted but it happens automatically (code never goes in ViewDidLoad)

Thanks
Guru

Caul58 said...

Thanks for your code. I have a question, when my view load it don't let me interact with the tableview until I press the searchbar. Did you get this issue?

Brian Slick said...

Guru> While you are on the 2nd view, force a memory warning. When you go back, you should see viewDidLoad fire.

Caul58> No

Guru said...

Hi Brian

This is what I did, but I dont quite understand behaviour. I was more interested in this small snippet in viewDidLoad


if ([self savedSearchTerm]){
[[[self searchDisplayController] searchBar] setText:[self savedSearchTerm]];
}


1) I search the term and I see new filtered table list
2) I select the cell which takes me to new View ( I added)
3) In simulator under Hardware->Simulate Memory Warning

but code dont go in the part I'm interested to see. Also it always goes one view behind from where I thought I am on (or the view currently displayed

At least if you Can you please describe
us what that code is useful for I can search myself

BTW - I read all the 5 parts and they are SUPER, I learned a lot in last few days ... Thanks a lot for sharing it!

Guru

Guru said...

Sorry I think I know what you meant earlier, please ignore my earlier comment. But when I simulate
Memory Warning

1) SearchViewController - viewDidUnload get called in which I see that

searchDisplayController:searchBar:text = (null) and this (nil) is being set to [self setSavedSearchTerm]

2) So When I come back from my new view back to search View in ViewDidLoad method doesn't find any searchTerm and hence code never goes inside that "if" condition...

wonder..if there is way to simulate this or comment out this line [self setSearchResults:nil] in viewDidUnload just to see how it behaves..

Thanks again
Guru

Brian Slick said...

Well, the point is to save and recover the search term if necessary. Possibly I made a mistake, or possibly something has changed. You'll just have to figure something out for yourself.

Apps by Gad said...

I am getting index 5 out of bounds [0....4] please help... I did exactly what you said.
Thanks

Brian Slick said...

No you didn't.

Anonymous said...

I'm getting an expected identifier error. I did do what you said, I've even copied and pasted everything just incase. I'd tell you what line it's on but XCode is crap.

Brian Slick said...

Download the provided sample project. Does the sample project have the problem? If no, then you did something wrong.