0

I have a UISearchDisplayController on a UITableView. The UITableView grabs JSON data from a server, breaks it down, and an object class takes that data and creates objects. It adds the Objects to a Mutable array to then use as the datasource for the table.

There is also another Mutable array used as the 'filtered' objects.

It's declared like so:

self.filteredItems = [NSMutableArray arrayWithCapacity:[self.items count]];

When I try to search the table I get this error:

Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 2 beyond bounds [0 .. 1]'

This is the code I'm using to do the filtering, which I found after going through a bunch of tutorials, I can't use NSPredicate because it seems the return function returns an NSArray, and I have an NSMutableArray, which I can not change because i'm not declaring the objects statically.

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{    
    /*
     Update the filtered array based on the search text and scope.
    */

    [self.filteredItems removeAllObjects];

    for (Update *update in items)
    {        
        if ([scope isEqualToString:@"Serial Number"]) {
            NSComparisonResult result = [[update Serial_Number] compare:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])];
            if (result == NSOrderedSame){
                [filteredItems addObject:update];
            }
        } else if ([scope isEqualToString:@"Ticket Number"]) {
            NSComparisonResult result = [[update Ticket_Number] compare:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])];
            if (result == NSOrderedSame){
                [filteredItems addObject:update];
            }
        } else if ([scope isEqualToString:@"Customer"]) {
            NSComparisonResult result = [[update Customer] compare:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])];
            if (result == NSOrderedSame){
                [filteredItems addObject:update];
            }
        }
    }
}

Not too sure what I'm doing wrong, I've never tried to implement this control before.

I actually ran break points, I can see that the objects are getting added to the filtered array, but then suddenly it crashes.

If you need any other part of the code to help me please let me know.

Thank you!

Edit:

Here's the delegate methods:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    if (updatesTableView == self.searchDisplayController.searchResultsTableView) {
        return [self.filteredItems count];
    } else  {
        return [self.items 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:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    Update *update = nil;

    if (tableView == self.searchDisplayController.searchResultsTableView) {
        update = [filteredItems objectAtIndex:indexPath.row];
    } else {
        // Configure the cell...
        update = [items objectAtIndex:indexPath.row];
    }

    [[cell textLabel] setText:[update Serial_Number]];
    [[cell detailTextLabel] setText:[NSString stringWithFormat:@"Customer: %@", [update Customer]]];

    cell.textLabel.adjustsFontSizeToFitWidth = YES;
    cell.detailTextLabel.adjustsFontSizeToFitWidth = YES;
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;    
}

The normal table displays just fine as well as their detail views.

Anthony
  • 648
  • 1
  • 7
  • 22
  • Can you post the datasource methods. Something may be going wrong with them. numberOfRows: may be returning the actual objects count, instead of filtered objects count. – nkongara Mar 17 '13 at 16:55
  • "I can't use NSPredicate because it seems the return function returns an NSArray, and I have an NSMutableArray, which I can not change because i'm not declaring the objects statically" - That remark makes no sense. And in any case you can turn an NSArray into an NSMutableArray easily and with no overhead. – matt Mar 17 '13 at 17:26

2 Answers2

1

In your delegate methods you have in 'numberOfRows':

if (updatesTableView == self.searchDisplayController.searchResultsTableView) {

then in 'cellForRowAtIndexPath':

if (tableView == self.searchDisplayController.searchResultsTableView) {

You're comparing different tables for determining the number of rows and then which array to get the data from.

miwic
  • 70
  • 1
  • 6
  • Excellent! That fixed the crash, however now no matter what I type it returns all of the rows for the search. What could cause that? – Anthony Mar 17 '13 at 17:22
  • Great! Is your 'updatesTableView' variable set correctly (outlets set in interface builder), or assigned in viewDidLoad? – miwic Mar 17 '13 at 17:30
  • The table loads the data correctly on load, then you hit the search bar and it activates the display controller, when you start typing it just returns all of the rows back into the searchdisplaycontroller tableView. WHich makes me think that the filterContentForSearchText is not working correctly. But it looks ok to me, but I've never done this before. – Anthony Mar 17 '13 at 17:32
  • Unfortunately, I haven't used it either. In the past, I have generally had a table and put a UISearchBar at the top, set the delegates and implemented the delegate methods. From the look of it, you may find that updatesTableView was nil which is why you were getting the array out of bounds exception and the fact you get the same results all the time. – miwic Mar 17 '13 at 17:38
  • Ah ha! I found it. I was using updatesTableView in both delegate methods, which I just realized looked weird. So i switched it to tableView, and all works well! Thank you for your help! – Anthony Mar 17 '13 at 17:41
1
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return [self.filteredItems count];
    } else  {
        return [self.items count];
    }
}
Pradeep
  • 563
  • 1
  • 3
  • 16