49 votes

UITableView reloadData appelle automatiquement resignFirstResponder

J'ai un UITableView avec des cellules personnalisées qui ne peuvent recevoir que des valeurs prédéfinies. J'utilise donc un UIPickerView comme inputView. Tout va très bien jusqu'à ce que je modifie un champ et que je doive afficher sa valeur mise à jour.

Afin de rendre les choses plus claires et plus faciles à maintenir, j'ai fait des délégués et des sources de données des classes séparées, et j'utilise des notifications pour les faire interagir avec le tableView. Ainsi, après qu'une valeur ait été choisie dans l'UIPickerView, la source de données du tableView est notifiée, et à son tour notifie le ViewController principal qui détient une référence au tableView. De là, j'appelle

[_tableView reloadData];

et tout semble fonctionner, sauf que l'UIPickerView disparaît, je pense que c'est parce que les cellules sont régénérées et que quelque part un resignFirstResponder est appelé, ou quelque chose comme ça. Existe-t-il un autre moyen de faire en sorte que le tableView mette à jour ses valeurs sans avoir à implémenter une méthode personnalisée quelque part qui le fasse, ce qui serait assez laid ?

2 votes

Avez-vous essayé de ne pas recharger la vue entière du tableau, mais seulement la ligne concernée ? Essayez cette méthode : -reloadRowsAtIndexPaths:withRowAnimation :

0 votes

Resings ? hehe Oh la différence que fait l'échange de deux lettres. :-)

0 votes

Cela ne semble pas simple, vous devrez peut-être fournir des informations plus détaillées.

24voto

Eiko Points 19502

Cela ressemble à un comportement attendu - le sélecteur appartient à une cellule particulière, cette cellule est rechargée et n'est plus le premier répondant. I devinez il fallait de toute façon sélectionner un élément spécifique pour que le sélecteur apparaisse, c'est-à-dire pour qu'il soit le premier répondant.

Vous devez donc soit faire en sorte qu'il redevienne le premier intervenant après le rechargement, soit mettre à jour la cellule spécifique directement.

0 votes

En fait, j'ai mis à jour la cellule spécifique directement, bien qu'elle me semble encore assez sale.

22voto

valvoline Points 2358

En ajoutant :

[yourSearchBar becomeFirstResponder];

après votre :

[_tableView reloadData];

a fait l'affaire

9 votes

Cela a fonctionné pour moi dans iOS 5. Cependant, sous iOS 6, cela ne fonctionne pas. Après avoir appelé [_tableView reloadData], les données ne sont pas rechargées tout de suite, mais après le retour de la méthode. J'ai dû retravailler mon code pour utiliser les méthodes UITableView insertXXX, reloadXXX et removeXXX au lieu de recharger toutes les données. Si vous connaissez une méthode compatible avec iOS 6, veuillez la partager.

0 votes

Cela fonctionne pour moi sur iOS 8 et 9 ;)

1 votes

//Posez un délai pour la mise à jour de l'animation et le processus de rechargement de la table //spécialement pour ios11 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [yourSearchBar becomeFirstResponder] ; }) ; Cette astuce fonctionnera.

9voto

Carlos Ricardo Points 1204

Vous pouvez suivre cette approche, pas la meilleure, mais elle fonctionne :

// pass the responder to a temporary (hidden) textField
[_tmpTextField becomeFirstResponder];

// reload data
[_tableView reloadData];

// reloadData is definitely async... 
// so pass the responder back in a timed op
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [_textField becomeFirstResponder];
});

2 votes

J'ai essayé ça. Le clavier semble disparaître très brièvement, puis réapparaître immédiatement. Peut-être n'ai-je pas fait mon _tmpTextField correctement. Je suis juste en train d'en faire un avec [[UITextInput alloc] init] puis le définir comme premier répondant. Étant donné que je suis dans une instance de UITableViewController, je ne vois pas où le mettre. Vous avez besoin d'aide ?

2 votes

C'est très intéressant et ça marche pour moi ! !! Le clavier apparaît plus rapidement s'il est configuré delayInSeconds à 0,1 mais s'il est réglé sur 0,001, il fonctionne ! Peut-être que cela cause des problèmes de performance... Je ne sais pas.

8voto

Joris Weimar Points 771

J'ai résolu ce problème en sous-classant UITextView, en surchargeant -(BOOL)resignFirstResponder et en ajoutant un BOOL canResign. Cette variable est définie avant le rechargement des données et est désactivée peu de temps après.

1 votes

Pouvez-vous fournir plus de détails sur votre solution ? cela m'aiderait beaucoup. merci.

0 votes

Je pense que j'ai fourni les détails... vous sous-classez UITextView override resignFirstResponder et seulement return ([super resignFirstResponder] && self.canResign) ; à partir de votre code, vous devez définir textView.canResign = NO... et ensuite un performSelector :... afterDelay :... qui définit canResign = YES

2 votes

Alors vous ne l'avez probablement pas implémenté correctement. Cela fonctionne bien pour moi.

0voto

adbie Points 255

Si vous êtes confronté à ce problème avec une barre de recherche, voici ce qui a fonctionné pour moi dans iOS 6 :

  • Instanciez une barre de recherche UISearchBar et ajoutez-la en tant qu'élément de l'interface utilisateur. vue secondaire à votre UITableView en haut.
  • Créez une première cellule fictive dans votre UITableView afin que la barre de recherche ne bloque que cette cellule fictive et non la cellule réelle contenant les données.

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