2 Stimmen

UISearchResultsController stürzt auf dem Gerät ab (Index außerhalb der Grenzen für leeres Array)

Ich benutze UISearchResultsController zum Filtern von Daten aus einer fetchedResultsController . Hier ist der entsprechende Code:

Sur RootVieweController.h :

@interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate, AdditionViewControllerDelegate, UISearchBarDelegate, UISearchDisplayDelegate> {

    NSArray *filteredListContent;   
    NSString *savedSearchTerm;
    NSInteger savedScopeButtonIndex;
    BOOL searchIsActive;
}
@property (nonatomic, retain) NSArray *filteredListContent;
@property (nonatomic, copy) NSString *savedSearchTerm;
@property (nonatomic) NSInteger savedScopeButtonIndex;
@property (nonatomic) BOOL searchIsActive;

Sur RootViewController.m :

-(void)viewDidLoad {
    [snip]
    UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 300, 40)];
    searchBar.delegate = self;
    searchBar.scopeButtonTitles = [NSArray arrayWithObjects:@"Scope 1", @"Scope 2", nil];
    [searchBar sizeToFit];
    searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
    self.tableView.tableHeaderView = searchBar;
    [searchBar release];
    [self.tableView setContentOffset:CGPointMake(0, 40)];

    UISearchDisplayController *searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
    [self performSelector:@selector(setSearchDisplayController:) withObject:searchDisplayController];

    [searchDisplayController setDelegate:self];
    [searchDisplayController setSearchResultsDataSource:self];
    [searchDisplayController setSearchResultsDelegate:self];
    [searchDisplayController release];

    self.filteredListContent = [NSMutableArray arrayWithCapacity:[[[self fetchedResultsController] fetchedObjects] count]];

    if (self.savedSearchTerm) {
        [self.searchDisplayController setActive:self.searchIsActive];
        [self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
        [self.searchDisplayController.searchBar setText:savedSearchTerm];

        self.savedSearchTerm = nil;
    }
}

- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    if (theTableView == self.searchDisplayController.searchResultsTableView) {
        NSLog(@"Search Cells: %i", [self.filteredListContent count]);
        return [self.filteredListContent count];
    }
    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
    NSLog(@"Normal cells: %i", [sectionInfo numberOfObjects]);
    return [sectionInfo numberOfObjects];
}

-(void)configureCell:(CustomTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    //Called from cellForRowAtIndexPath

    Object *object = nil;
    if (self.searchIsActive) {
        object = [[self filteredListContent] objectAtIndex:[indexPath row]];
    } else {
        object = [fetchedResultsController objectAtIndexPath:indexPath];
    }

    [snip]
}

#pragma mark -
#pragma mark Search functions

-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope {
    if ([scope isEqualToString:@"Scope 1"]) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"scope1 BEGINSWITH[cd] %@", searchText];
        self.filteredListContent = [[[self fetchedResultsController] fetchedObjects] filteredArrayUsingPredicate:predicate];
    } else {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"scope2 BEGINSWITH[cd] %@", searchText];
        self.filteredListContent = [[[self fetchedResultsController]fetchedObjects] filteredArrayUsingPredicate:predicate];
    }
}

#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods

- (void)searchDisplayController:(UISearchDisplayController *)controller willShowSearchResultsTableView:(UITableView *)theTableView {
    NSLog(@"Showing search results");
}

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    [self filterContentForSearchText:searchString scope:
     [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:
      [self.searchDisplayController.searchBar selectedScopeButtonIndex]]];

    NSLog(@"Reloading for string");

    return YES;
}

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
     [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];

    NSLog(@"Reloading for scope");

    return YES;
}

-(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    self.searchDisplayController.searchResultsTableView.rowHeight = 55;
    self.searchIsActive = YES;
}

-(void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller {
    self.searchIsActive = NO;
}

Im Simulator funktioniert das hervorragend. Aber auf einem Gerät stürzt es ab, wenn object = [[self filteredListContent] objectAtIndex:[indexPath row]]; de configureCell beim Versuch, die searchResultsTableView anzuzeigen. Ich erhalte den Fehler [NSMutableArray objectAtIndex:]: index 7 beyond bounds for empty array . Immer Index 7. Was übersehe ich hier?

--UPDATE--

Behoben: Umdrehen der searchIsActive BOOL zum Einschalten searchDisplayControllerDidBeginSearch anstelle von searchDisplayControllerWillBeginSearch y searchDisplayControllerWillEndSearch anstelle von searchDisplayControllerDidEndSearch . Dadurch wird verhindert, dass die Tabelle versucht, Zellen zu konfigurieren, die nicht vorhanden sind. Keine Ahnung, warum der Simulator das nicht bemerkt hat

0voto

iwasrobbed Punkte 45760

Wenn das Array, auf das verwiesen wird, leer ist, spielt es keine Rolle, welcher Index es ist, wenn Sie versuchen, den Tableview aus einem leeren Array zu füllen.

Ist Ihr NSMutableArray filteredListContent bestückt (d.h. geben Sie Suchergebnisse aus dem Controller für abgeholte Ergebnisse zurück)? Haben Sie den Inhalt des Arrays in filterContentForSearchText: ?

P.S. Ich mag deinen Stil... BeerListTableViewCell :)

0voto

dmkash Punkte 1247

Ich bin auf Folgendes gestoßen genau derselbe Absturz während der Arbeit an einer Aktualisierung einer bestehenden App. Der Code ist fast genau derselbe wie der des ursprünglichen Posters, und das Einzige, was sich in meiner Anwendung geändert hat, war die Datenbank. Es gab keine Code-Änderungen .

Bei der alten Datenbank werden die Datasource-Methoden der Tabellensicht nicht aufgerufen, wenn der Suchanzeige-Controller eine Suche startet.

Mit der neuen Datenbank werden die Datenquellenmethoden des Tabellenviews faire werden aufgerufen, wenn der Controller der Suchanzeige eine Suche startet.

Dieselben Core Data-Entitäten, dieselbe Datenbankstruktur, derselbe Code, dieselben Nibs. Gleiches Problem im Simulator oder auf dem Gerät.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X