Lag / delay super lent sur l'animation initiale du clavier de UITextField

169

D'accord, ce problème me rend fou.

Il faut environ 3 à 4 secondes pour que le clavier apparaisse après avoir touché mon UITextField. Cela ne se produit que la première fois que le clavier apparaît depuis le lancement de l'application, puis l'animation démarre instantanément.

Au début, je pensais que c'était un problème de chargement de trop d'images, ou mon UITableView, mais je viens de créer un tout nouveau projet avec seulement un UITextField, et je rencontre toujours ce problème. J'utilise iOS 5, Xcode ver 4.2 et fonctionne sur un iPhone 4S.

Voici mon code:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 20, 280, 30)];
    textField.borderStyle = UITextBorderStyleRoundedRect;
    textField.delegate = self;
    [self.view addSubview:textField];
}

@end

Est-ce un problème courant pour toutes les applications?

Pour le moment, la seule façon de l'améliorer un peu est d'être textFielddevenu / démissionner premier intervenant viewDidAppear, mais cela ne résout pas entièrement le problème - cela charge simplement le délai lorsque la vue se charge à la place. Si je clique sur textFieldimmédiatement lors du chargement de la vue, le problème persiste; si j'attends 3-4 secondes après le chargement de la vue avant de toucher le champ textField, je n'obtiens pas le délai.

Vadoff
la source

Réponses:

291

Avant de mettre en œuvre des hacks exotiques pour contourner ce problème, essayez ceci: arrêtez la session de débogage, fermez l'application du multitâche, débranchez votre appareil de l'ordinateur et exécutez l'application normalement en appuyant sur son icône. J'ai vu au moins deux cas dans lesquels le retard ne se produit que lorsque l'appareil est branché.

Cendre
la source
2
C'était la bonne réponse dans mon cas sur un iPhone 5 exécutant iOS 8.1 - je rencontrais un délai d'environ 1 seconde pour le premier clavier.
bejonbee
7
Oui, le décalage se produit uniquement lors du débogage. Bizarre.
Pauls
16
Je vous remercie. Ce problème est toujours présent sur iOS 9.1 / Xcode 7.1, Swift 2.1.
Yaroslav
4
FYVM Apple, FYVM. 90 minutes de temps avec une date limite que je ne peux pas me permettre. 20 votes positifs si je pouvais. Toujours présent dans iOS9.2 / Xcode 7.2
BaseZen
1
C'était exactement ce que mon problème était aussi. Après avoir été débranché de mon mac, il n'y avait aucun délai (ios9) xcode 7.2
Déconseillé Darren
148

Donc, le problème n'est PAS seulement limité à la première installation comme je l'avais pensé auparavant, mais se produit à chaque fois que l'application est lancée. Voici ma solution qui résout complètement le problème.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Preloads keyboard so there's no lag on initial keyboard appearance.
  UITextField *lagFreeField = [[UITextField alloc] init];
  [self.window addSubview:lagFreeField];
  [lagFreeField becomeFirstResponder];
  [lagFreeField resignFirstResponder];
  [lagFreeField removeFromSuperview];
}
Vadoff
la source
1
Nice and simple @Vadoff - ceci est une version en ligne de l'exemple UIResponder + KeyboardCache donné ci
amergin
4
Cela aurait dû être géré par le système d'exploitation ... mais bon: /
chakrit
9
Merci! le problème persiste malheureusement sur ios8, mais cette solution de contournement le résout toujours
hitme
1
@Vadoff Solution fonctionne, mais a 2 inconvénients: 1) J'ai environ 1 seconde supplémentaire de chargement d'application; 2) Avertissement de mémoire reçu (mais pas tout le temps). J'ai essayé d'ajouter ce code à UIViewController dans viewDidLoad, mais je n'ai eu aucun effet, peut-être ai-je fait quelque chose de mal? Pourriez-vous modifier votre réponse et ajouter un code pour le contrôleur de vue, si cela est possible.
Dima Deplov
16
Le fait que ce soit la bonne réponse et fonctionne me fait pleurer. J'ai dû prendre une douche après avoir appliqué ce hack.
Bill Burgess
27

Ouais, j'ai aussi eu quelques secondes de retard sur le dernier iPhone 4s. Ne paniquez pas. Pour certaines raisons, cela ne se produit que la première fois que l'application est chargée à partir de Xcode dans Debug. Quand j'ai fait Release, je n'ai pas de retard. Oublie ça ...

Bonjour le monde
la source
6
Il est dû au niveau d'optimisation: Fastest, Smallest [-Os]. Vous pouvez le changer leBuild Settings > Optimization Level
Carlos Ricardo
20

C'est un problème connu.

Le préchargement du clavier semble prometteur. Vérifiez le préchargement du UIKeyboard.

Quelques lectures supplémentaires:

L'affichage initial du clavier virtuel de l'iPhone est lent pour un UITextField. Ce hack est-il nécessaire?

Le clavier UITextField bloque la boucle d'exécution lors du chargement?

http://www.iphonedevsdk.com/forum/iphone-sdk-development/12114-uitextfield-loooong-delay-when-first-tapped.html

Rok Jarc
la source
3
Merci, de nombreux liens mentionnent que le délai est d'environ "1 seconde sur les anciens iPhone", "pas si perceptible sur le 3G" et "se charge instantanément sur les nouveaux appareils", mais je rencontre un délai beaucoup plus long de 3-4 secondes sur un iphone 4s. Je vais essayer de précharger le clavier ensuite, mais je crains que quelque chose d'autre puisse être un problème (peut-être ios5 ou mon xcode ver?).
Vadoff
Avez-vous essayé comment UITextField et le clavier se comportent dans une application native? Assurez-vous de le retirer de la mémoire avant ce test (double 'clic' sur le bouton d'accueil ...). Il n'y a rien de mal avec le morceau de code que vous avez posté et 3-4 secondes semblent vraiment beaucoup - trop. Je n'ai jamais essayé ce préchargement, mais cela semble être la seule solution de contournement.
Rok Jarc
Oui, le champ de recherche textField pour Maps fait apparaître le clavier instantanément lorsque vous cliquez dessus après le lancement. Je l'ai retiré de la mémoire et essayé plusieurs fois, c'est instantané à chaque fois. Je ne suis pas sûr de savoir pourquoi le mien est si lent.
Vadoff
Je viens de faire un test sur l'une de mes applications qui utilisent UITextField - le décalage devrait vraiment être minime. Le code que vous avez publié semble correct, il doit donc y avoir quelque chose d'autre retenant le fil de discussion principal. Cela pourrait être le bon moment pour lancer les fameux Instruments.
Rok Jarc
23
D'accord, pour toute autre personne qui semble avoir ce problème. J'ai découvert que cela ne s'était produit que la première fois que l'application était mise à jour sur l'iPhone à partir de xcode. Une fois l'application chargée sur l'iPhone, toute utilisation ultérieure avec l'application entraînera un comportement normal (j'ai supprimé le programme de la mémoire plusieurs fois / redémarré mon iPhone pour m'en assurer).
Vadoff
18

Vous pouvez utiliser la solution de Vadoff dans Swift en ajoutant ceci à didFinishLaunchingWithOptions:

// Preloads keyboard so there's no lag on initial keyboard appearance.
let lagFreeField: UITextField = UITextField()
self.window?.addSubview(lagFreeField)
lagFreeField.becomeFirstResponder()
lagFreeField.resignFirstResponder()
lagFreeField.removeFromSuperview()

Cela fonctionne pour moi dans iOS 8.

Greg
la source
5

Code dans le bloc ajouté à la file d'attente principale et exécuté de manière asynchrone. (ne pas verrouiller le thread principal)

dispatch_async(dispatch_get_main_queue(), ^(void){
      [textField becomeFirstResponder];
 });
Sergey Petruk
la source
6
Essayez d'ajouter une explication textuelle qui décrit pourquoi votre code fonctionne et non pas simplement de la donner afin que d'autres puissent en tirer des leçons.
Traîneau
7
Ce code bloque en fait le thread principal, vous distribuez sur la file d'attente principale ...
Werner Altewischer
connaissez-vous la différence entre dispatch_async / dispatch_sync? Et pensez-vous que [textField devientFirstResponder]; est très difficile pour le fil principal?
Sergey Petruk
@Spetruk Le thread appelant dispatch_async n'est pas bloqué, mais le thread sur lequel vous exécutez le code est définitivement bloqué. Un seul thread ne peut pas faire deux choses à la fois, donc ce code bloque le thread principal (à cause de dispatch_get_main_queue) mais ne bloque pas le thread où dispatch_async est appelé.
Kevin le
@Kevin mais quelque chose bloque le thread principal et l'animation du clavier ne fonctionne pas. Je suis d'accord avec vous, mais à mon avis, la solution avec textFiled dans appDelegate sent mauvais.
Sergey Petruk
1

Un problème connexe, où un UIViewController serait lent à se présenter, a été résolu en utilisant la police système au lieu d'une police personnalisée sur UITextField. Peut-être que l'utilisation de la police système pourrait également résoudre ce problème?

Crashalot
la source
0

Ce bogue semble être corrigé dans iOS 9.2.1. Depuis la mise à niveau de mon appareil, je n'ai plus de délai entre le fait d'appuyer sur un champ de texte et l'apparition du clavier lorsque mon appareil est connecté à mon ordinateur.

Jeff Bowen
la source
1
il semble être corrigé sur l'iPhone mais j'ai toujours le décalage sur l'iPad.
Adarkas2302
0

Cette réponse sélectionnée provoque le crash de BAD_EXC sur iOS 11 - supprimer de l'application pour corriger

Manesh
la source
-2

Vous pouvez ajouter le code ci-dessous lorsque la vue de viewController a été chargée, comme viewDidAppear.Pas seulement application: didFinishLaunchingWithOptions:

UITextField *lagFreeField = [[UITextField alloc] init];
[self.window addSubview:lagFreeField];
[lagFreeField becomeFirstResponder];
[lagFreeField resignFirstResponder];
[lagFreeField removeFromSuperview];
Tianglin
la source