80 votes

Échec de l’assertion lorsque vous utilisez UISearchDisplayController dans UITableViewController

J'ai essayé d'ajouter une fonctionnalité de Recherche pour un TableViewController dans mon application. J'ai suivi Ray Wenderlich du tutoriel. J'ai un tableView avec certaines données, j'ai ajouté à la barre de recherche + contrôleur d'affichage dans la table de montage séquentiel, et puis j'ai ce code:

#pragma mark - Table View
     - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BreedCell" forIndexPath:indexPath];

        //Create PetBreed Object and return corresponding breed from corresponding array
        PetBreed *petBreed = nil;

        if(tableView == self.searchDisplayController.searchResultsTableView)
            petBreed = [_filteredBreedsArray objectAtIndex:indexPath.row];
        else
            petBreed = [_breedsArray objectAtIndex:indexPath.row];

        cell.accessoryType  = UITableViewCellAccessoryDisclosureIndicator;
        cell.textLabel.text = petBreed.name;

        return cell;
    }

#pragma mark - Search
    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
        [_filteredBreedsArray removeAllObjects];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",searchString];
        _filteredBreedsArray = [[_breedsArray filteredArrayUsingPredicate:predicate] mutableCopy];

        return YES;
    }

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
        // Tells the table data source to reload when scope bar selection changes

        [_filteredBreedsArray removeAllObjects];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",self.searchDisplayController.searchBar.text];
        _filteredBreedsArray = [[_breedsArray filteredArrayUsingPredicate:predicate] mutableCopy];
        return YES;
    }

La norme des choses, mais quand j'ai entrer le texte dans la barre de recherche, il plante à chaque fois avec cette erreur:

2013-01-07 19:47:07.330 FindFeedo[3206:c07] *** Assertion failure in -[UISearchResultsTableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:4460
2013-01-07 19:47:07.330 FindFeedo[3206:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier BreedCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

Je comprends que dans iOS 6, la manipulation et dequeueing système pour les cellules changé, et aussi que la recherche utilise un autre tableView, j'ai donc pensé que le problème était que la recherche de la tableView avec les résultats filtrés ne savais pas à propos de la cellule, alors j'ai mis ça dans mon viewDidLoad:

[self.searchDisplayController.searchResultsTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"BreedCell"];

Et le tour est joué! Il a travaillé... Seulement la première fois que vous recherchez. Si l'on remonte à l'origine des résultats et de la recherche, de nouveau, l'application se bloque avec la même erreur. J'ai pensé peut-être l'ajout de tous les

if(!cell){//init cell here};

des trucs à la cellForRow méthode, mais n'est-ce pas aller à l'encontre de l'objectif de la dequeueReusableCellWithIdentifier:forIndexPath: méthode? De toute façon, je suis perdu. Ce qui me manque? Aider, s'il vous plaît. Je vous remercie à l'avance pour tout votre temps (:

Alex.

193voto

FunkyKat Points 1488

Essayez d’utiliser self.tableView au lieu de tableView dans dequeueReusableCellWithIdentifier :

Ce code fonctionne très bien

Remarque

Si vous avez des cellules de taille personnalisée, n’utilisez pas

Utilisez-le à la place

14voto

Daniel Points 14150

La raison pour laquelle il a travaillé beaucoup sur la première manche mais avant de s'écraser si vous quittez la table de résultats, et suis de retour pour une autre recherche est parce que la Recherche Contrôleur d'Affichage est le chargement d'un nouveau UITableView chaque fois que vous entrez dans le mode de recherche.

En mode de recherche, je veux dire, vous avez puisé les textfield et vous avez commencé à écrire, à quel point une vue de table est générée à l'affichage des résultats, de quitter ce mode, il atteint en appuyant sur le bouton annuler. Lorsque vous appuyez sur le textfield la deuxième fois et de commencer à taper de nouveau - c'est l'entrée dans "mode de recherche" pour la deuxième fois.

Afin d'éviter le crash, vous devez vous inscrire à la cellule de la classe pour l'affichage de la table à utiliser dans l' searchDisplayController:didLoadSearchResultsTableView: délégué de la méthode (à partir de UISearchDisplayDelegate) de la place dans vos contrôleurs viewDidLoad méthode.

Comme suit:

- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
    [tableView registerClass:[DPContentTableCell class] forCellReuseIdentifier:cellIdentifier];
    [tableView registerClass:[DPEmptyContentTableCell class] forCellReuseIdentifier:emptyCellIdentifier];
}

Cela m'a pris par surprise parce que sur iOS 7... la vue de la table est d'être réutilisées. Ainsi, vous pouvez enregistrer la classe en viewDidLoad si vous préférez. L'héritage pour cause de vous, je vais garder mon inscription à la méthode du délégué je l'ai mentionné.

12voto

aqubi Points 31

Après une recherche, « tableView » de la méthode cellForRowAtIndexPath ne semble pas être une instance de la Table que vous définissez. Ainsi, vous pouvez utiliser une instance d’un tableau qui définit la cellule. Au lieu de :

Utilisation :

(Ne pas utiliser les tableView de méthode cellForRowAtIndexPath, utilisez self.tableView.)

3voto

skaman Points 41

Dequeue la cellule sans utiliser le « indexPath » et dans le cas de vous obtenir un élément de zéro, vous devrez renvoyer manuellement.

Essayez d’utiliser self.tableView pour enlever la cellule peut provoquer des pannes quand vous avez une liste principale sectionnée et une liste de recherche simple. Au lieu de cela, ce code fonctionne dans n’importe quelle situation.

2voto

sonicbabbler Points 129

Je travaille également sur ce tutoriel. La valeur par défaut TableViewController a « forIndexPath » et dans son cas il n’existe pas. Une fois que je l’ai enlevé les travaux de recherche.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X