Reputation: 12051
My app crashes if I do this:
I make a search on my UITableView
After a search I tap on UITableViewCell of searchDisplayController
UITableView and go to another View Controller
I then come back to the main UITableView, questionTable
- the one in which I searched, and tap on the last cell, or any cell that is greater then the number of search results I previously had.
App crashes with this error:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 12 beyond bounds [0 .. 0]'
*** First throw call stack:(0x35aa188f 0x37e48259 0x359ea9db 0x155fd 0x3384df5b 0x153ed 0x3358793d 0x33601627 0x355bb933 0x35a75a33 0x35a75699 0x35a7426f 0x359f74a5 0x359f736d 0x37693439 0x33503cd5 0x95a3 0x9548) terminate called throwing an exception(lldb)
I suspect the problem is with my code, because searching UITableView is a new topic for me. That's how I do it:
1.My VC conforms to these protocols <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate>
2.I have these variables:
@property (nonatomic, retain) NSMutableArray *searchResults;
@property (nonatomic, copy) NSString *savedSearchTerm;
3. In viewDidLoad
i set up the source of my UITableView which I search:
self.questionList = [[NSArray alloc]
initWithObjects: MY OBJECTS HERE, nil];
if ([self savedSearchTerm])
{
[[[self searchDisplayController] searchBar] setText:[self savedSearchTerm]];
}
4. I have this action to handle the search:
- (void)handleSearchForTerm:(NSString *)searchTerm
{
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
}
[[self searchResults] removeAllObjects];
if ([[self savedSearchTerm] length] != 0)
{
for (NSString *currentString in [self questionList])
{
if ([currentString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
{
[[self searchResults] addObject:currentString];
}
}
}
}
5) Here's how I set up my UITable views:
(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = [indexPath row];
NSString *contentForThisRow = nil;
if (tableView == [[self searchDisplayController] searchResultsTableView])
contentForThisRow = [[self searchResults] objectAtIndex:row];
else
contentForThisRow = [[self questionList] objectAtIndex:row];
static NSString *CellIdentifier = @"questionsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[[cell textLabel] setText:contentForThisRow];
return cell;
}
6) Here's how my numberOfRowsInSection
method looks like:
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows;
if (tableView == [[self searchDisplayController] searchResultsTableView])
rows = [[self searchResults] count];
else
rows = [[self questionList] count];
return rows;
}
7) Finally, I have these two methods:
(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self handleSearchForTerm:searchString];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
(void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
[self setSavedSearchTerm:nil];
[[self questionTable] reloadData];
}
I'm really sorry for the long question. I have made some mistake in the code and I hope someone could show me the right way to do this. The Search Bar Controller is properly linked in the IB Any help would be highly appreciated!
NEW EDIT:
I'm pushing a new VC on didSelectRowAtIndePath
:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:@"toAnswer" sender:indexPath];
}
And I'm updating an NSString there. It worked perfectly when I used just one TableView
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
((QandADetailsViewController *)segue.destinationViewController).delegate=self;
NSIndexPath *indexPath = (NSIndexPath *)sender;
QandADetailsViewController *mdvc = segue.destinationViewController;
if (self.searchResults == nil) {
mdvc.questionName = [self.questionList
objectAtIndex:indexPath.row];
} else {
mdvc.questionName = [self.searchResults
objectAtIndex:indexPath.row];
}
}
Upvotes: 2
Views: 729
Reputation: 62676
In prepare for segue, the check for searchResults == nil is probably incorrect. There's no reason to expect it to be nil ever after the first search. That means you'll always be dereferencing the search array on subsequent table selections, explaining the index out of bounds.
The fix, I think, is to ask if ([self.searchDisplayController isActive])
instead of whether search results exist.
Upvotes: 3
Reputation: 5771
it seems that your array is empty.
i would recommend you to log your array after every step you do, so you can see where it gets empty.
also log the line number and method names, see this, how to log:
NSLog(@"%s\n [Line: %d]\n array:%@\n\n", __PRETTY_FUNCTION__, __LINE__, yourArray);
Upvotes: 1