Reputation: 888
I have a IUSearchBar with an UISearchDisplayController, and everything is working well:
screenshot 1 http://joeranbosma.nl/xcode/sdc1.png
screenshot 1 http://joeranbosma.nl/xcode/sdc2.png
But, here it comes!
screenshot 1 http://joeranbosma.nl/xcode/sdc3.png
When I then click on the clear (x) button, the program crashes with a SIGABRT error:
screenshot 1 http://joeranbosma.nl/xcode/sdc4.png
.. and I have no idea how to fix this :(
Here is my source code: (no idea what you need to solve the question) http://joeranbosma.nl/xcode/wearch_stack.zip
But I think this is the most useful part:
- (void)viewDidLoad {
[super viewDidLoad];
//Initialize the array.
listOfItems = [[NSMutableArray alloc] init];
copyListOfItems = [[NSMutableArray alloc] init];
staticlist = [[NSMutableArray alloc] init];
staticlist = listOfItems;
//Add items
[listOfItems addObject:@"Iceland"];
[listOfItems addObject:@"Greenland"];
[listOfItems addObject:@"Switzerland"];
[listOfItems addObject:@"Norway"];
[listOfItems addObject:@"New Zealand"];
[listOfItems addObject:@"Greece"];
[listOfItems addObject:@"Rome"];
[listOfItems addObject:@"Ireland"];
//Set the title
self.navigationItem.title = @"Wearch";
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (searching)
return [copyListOfItems count];
else {
return [listOfItems count];
}
}
// Customize the appearance of table view cells.
- (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] autorelease];
}
// Configure the cell.
if(searching)
cell.textLabel.text = [copyListOfItems objectAtIndex:indexPath.row];
else {
NSString *txtLbl = [listOfItems objectAtIndex:indexPath.row];
cell.textLabel.text = [txtLbl stringByAppendingString:@"x"];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Get the selected word
NSString *selectedWord = nil;
if(searching)
selectedWord = [copyListOfItems objectAtIndex:indexPath.row];
else {
selectedWord = [listOfItems objectAtIndex:indexPath.row];
}
//Initialize the detail view controller and display it.
DetailViewController *dvController = [[DetailViewController alloc] initWithNibName:@"DetailView" bundle:[NSBundle mainBundle]];
dvController.selectedWord = selectedWord;
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
dvController = nil;
}
- (void) searchBarTextDidBeginEditing:(UISearchBar *)theSearchBar {
searching = YES;
}
- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
//Remove all objects first.
[copyListOfItems removeAllObjects];
if([searchText length] > 0) {
searching = YES;
[self searchTableView];
}
else {
searching = NO;
}
[self.tableView reloadData];
}
- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar {
[self searchTableView];
}
- (void) searchTableView {
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
NSMutableArray *results1 = [[NSMutableArray alloc] init];
NSMutableArray *results2 = [[NSMutableArray alloc] init];
[searchArray addObjectsFromArray:listOfItems];
for (NSString *sTemp in searchArray) {
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0){
if (titleResultsRange.location == 0) {
[results1 addObject:sTemp];
}
else{
[results2 addObject:sTemp];
}
}
}
for (NSString *sTemp in results1) {
[copyListOfItems addObject:sTemp];
}
for (NSString *sTemp in results2) {
[copyListOfItems addObject:sTemp];
}
[searchArray release];
searchArray = nil;
}
I hope one of you can solve this.
Can you also say if you like the images?
Upvotes: 1
Views: 1228
Reputation: 27147
This is an interesting one. The long answer is that searchBarTextDidBeginEditing:
is being called after tableView:numberOfRowsInSection:
but before tableView:cellForRowAtIndexPath:
. The result is that the tableView
is expecting [listOfItems count]
number of rows but by the time it calls tableView:cellForRowAtIndexPath:
the searching
BOOL is YES
so the view controller uses copyListOfItems
to populate the table which of course does not contain a sufficient number of objects to populate the table.
The short answer is, stop telling the view controller you are searching until you are searching; Set searching = YES;
when there is actual text you are using to search not just when the searchBar
is first responder.
The really short answer:
- (void) searchBarTextDidBeginEditing:(UISearchBar *)theSearchBar {
// Comment this assignment out
//searching = YES;
}
It seems to work fine.
A couple of tips for such a scenario:
1) Look at the printed stacktrace in your console. It would have let you see that the problem was:
'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
2) Use NSLog
s profusely; I find the most helpful to be:
NSLog(@"%@",NSStringFromSelector(_cmd));
Edit In response to the non-symbolicated stack-trace in the console(i.e. 0x14d3ec9 0x36e5c2
):
3) Use an exception breakpoint; as pictured:
4) Add an uncaught exception handler; As described here.
Upvotes: 5