Bardzo wolne opóźnienie / opóźnienie początkowej animacji klawiatury UITextField


169

W porządku, ten problem doprowadza mnie do szału.

Klawiatura wyskakuje po około 3-4 sekundach od dotknięcia UITextField. Dzieje się tak tylko przy pierwszym wyskakiwaniu klawiatury od uruchomienia aplikacji, po czym animacja rozpoczyna się natychmiast.

Na początku myślałem, że to problem z wczytaniem zbyt wielu zdjęć lub moich UITableView, ale właśnie stworzyłem zupełnie nowy projekt z tylko jednym UITextFieldi nadal mam ten problem. Używam iOS 5, Xcode w wersji 4.2 i działam na iPhonie 4S.

To jest mój kod:

#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

Czy jest to wspólny problem dla wszystkich aplikacji?

W tej chwili jedynym sposobem, w jaki mogę to nieco poprawić, jest textFieldzostanie / zrezygnowanie z pierwszej pomocy viewDidAppear, ale to nie rozwiązuje problemu całkowicie - po prostu ładuje opóźnienie, gdy zamiast tego ładuje się widok. Jeśli kliknę textFieldnatychmiast po załadowaniu widoku, problem nadal występuje; jeśli poczekam 3-4 sekundy po załadowaniu widoku przed dotknięciem pola textField, nie otrzymam opóźnienia.

Odpowiedzi:


291

Zanim zaimplementujesz jakiekolwiek egzotyczne hacki, aby obejść ten problem, spróbuj wykonać następujące czynności: zatrzymaj sesję debugowania, zamknij aplikację przed wielozadaniowością, odłącz urządzenie od komputera i uruchom aplikację normalnie, dotykając jej ikony. Widziałem co najmniej dwa przypadki, w których opóźnienie występuje tylko wtedy, gdy urządzenie jest podłączone.


2
To była prawidłowa odpowiedź w moim przypadku na iPhonie 5 z systemem iOS 8.1 - miałem około 1-sekundowe opóźnienie dla pierwszej klawiatury.
bejonbee

7
Tak, opóźnienie występuje tylko podczas debugowania. Dziwne.
Pauls

16
Dziękuję Ci. Ten problem nadal występuje w iOS 9.1 / Xcode 7.1, Swift 2.1.
Jarosław

4
FYVM Apple, FYVM. 90 minut w terminie, na który mnie nie stać. 20 głosów poparcia, gdybym mógł. Nadal obecny w iOS9.2 / Xcode 7.2
BaseZen

1
Właśnie na tym polegał mój problem. Po odłączeniu od komputera Mac nie było opóźnienia (ios9) xcode 7.2
Darren

148

Tak więc problem NIE ogranicza się tylko do pierwszej instalacji, jak wcześniej myślałem, ale występuje za każdym razem, gdy aplikacja jest uruchamiana. Oto moje rozwiązanie, które całkowicie rozwiązuje problem.

- (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];
}

1
Ładny i prosty @Vadoff - jest to wbudowana wersja przykładu UIResponder + KeyboardCache podana poniżej
amergin

4
System operacyjny powinien to
załatwić

9
dzięki! problem nadal pozostaje na ios8 niestety, ale to obejście nadal go rozwiązuje
hitme

1
@Vadoff Rozwiązanie działa, ale ma 2 wady: 1) Mam około 1 dodatkowej sekundy ładowania aplikacji; 2) Otrzymano ostrzeżenie dotyczące pamięci (ale nie cały czas). Próbowałem dodać ten kod do UIViewController w viewDidLoad, ale nie przyniosło to efektu, może zrobiłem coś nie tak? Czy mógłbyś edytować swoją odpowiedź i dodać kod kontrolera widoku, jeśli to możliwe.
Dima Deplov

16
Fakt, że jest to poprawna odpowiedź i działa, sprawia, że ​​płaczę. Po zastosowaniu tego triku musiałem wziąć prysznic.
Bill Burgess

27

Tak, mam też kilka sekund opóźnienia na najnowszych iPhone'ach 4s. Nie panikuj. Z pewnych powodów dzieje się tak tylko przy pierwszym ładowaniu aplikacji z Xcode w debugowaniu. Kiedy wydałem Release, nie dostaję opóźnienia. Po prostu zapomnij...


6
To ze względu na poziom optymalizacji: Fastest, Smallest [-Os]. Możesz to zmienić naBuild Settings > Optimization Level
Carlos Ricardo

20

3
Dzięki, wiele linków wspomina o opóźnieniu wynoszącym około „1 sekunda na starszych telefonach iPhone”, „niezauważalne na 3g” i „natychmiastowe ładowanie na nowych urządzeniach”, ale doświadczam znacznie dłuższego opóźnienia wynoszącego 3-4 sekund na iPhonie 4s. Następnie spróbuję wstępnie załadować klawiaturę, ale obawiam się, że coś innego może być problemem (może ios5 lub moja wersja xcode?).
Vadoff,

Czy wypróbowałeś, jak UITextField i klawiatura zachowują się w natywnej aplikacji? Pamiętaj, aby usunąć go z pamięci przed tym testem (dwukrotnie „kliknij” przycisk strony głównej ...). Nie ma nic złego w opublikowanym fragmencie kodu, a 3-4 sekundy wydają się naprawdę dużo - za dużo. Nigdy nie próbowałem tego wstępnego ładowania, ale wygląda na to, że jest to jedyne obejście.
Rok Jarc,

Tak, pole tekstowe wyszukiwania w Mapach wyświetla klawiaturę natychmiast po kliknięciu po uruchomieniu. Usunąłem go z pamięci i próbowałem kilka razy, za każdym razem jest natychmiastowy. Nie jestem pewien, co się dzieje, dlaczego mój jest taki wolny.
Vadoff,

Właśnie wykonałem test na jednej z moich aplikacji, które używają UITextField - opóźnienie powinno być naprawdę minimalne. Kod, który opublikowałeś, wydaje się być w porządku, więc coś innego musi powstrzymywać główny wątek. To może być dobry moment na uruchomienie niesławnych Instruments.
Rok Jarc,

23
OK, dla każdego, kto wydaje się mieć ten problem. Odkryłem, że stało się to tylko przy pierwszej aktualizacji aplikacji na iPhonie z xcode. Gdy aplikacja zostanie załadowana na iPhone'a, wszelkie dalsze jej użycie spowoduje normalne zachowanie (kilka razy usunąłem program z pamięci / ponownie uruchomiłem iPhone'a, aby się upewnić).
Vadoff,

18

Możesz użyć rozwiązania Vadoffa w Swift, dodając to do 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()

U mnie działa w iOS 8.


5

Kod w bloku dodany do głównej kolejki i uruchamiany asynchronicznie. (nie blokuj głównego wątku)

dispatch_async(dispatch_get_main_queue(), ^(void){
      [textField becomeFirstResponder];
 });

6
Spróbuj dodać tekstowe wyjaśnienie, które opisuje, dlaczego Twój kod działa, a nie tylko go podawaj, aby inni mogli się z niego nauczyć.
Sled

7
Ten kod faktycznie blokuje główny wątek, który
wysyłasz

czy znasz różnicę między dispatch_async / dispatch_sync? I czy myślisz, że [textField staje sięFirstResponder]; jest bardzo trudne dla głównego wątku?
Sergey Petruk

@Spetruk Wątek wywołujący dispatch_async nie jest zablokowany, ale wątek, na którym faktycznie uruchamiasz kod, jest zdecydowanie zablokowany. Pojedynczy wątek nie może robić dwóch rzeczy naraz, więc ten kod blokuje główny wątek (z powodu dispatch_get_main_queue), ale nie blokuje wątku, w którym wywoływana jest metoda dispatch_async.
Kevin

@Kevin, ale coś blokuje główny wątek, przez co animacja klawiatury nie działa. Zgadzam się z tobą, ale moim zdaniem rozwiązanie z tekstemFiled w appDelegate brzydko pachnie.
Sergey Petruk


1

Powiązany problem, w którym UIViewController byłby wolny do prezentowania, został rozwiązany przy użyciu czcionki systemowej zamiast niestandardowej czcionki w UITextField. Być może użycie czcionki systemowej może również rozwiązać ten problem?


0

Ten błąd wydaje się być naprawiony w iOS 9.2.1. Od czasu aktualizacji urządzenia nie mam już opóźnienia między dotknięciem pola tekstowego a wyświetlaniem klawiatury, gdy moje urządzenie jest podłączone do komputera.


1
wydaje się, że został naprawiony na iPhonie, ale nadal mam opóźnienie na iPadzie.
Adarkas2302

0

Ta wybrana odpowiedź powoduje awarię BAD_EXC na iOS 11 - usuń z aplikacji, aby naprawić


-2

Możesz dodać poniższy kod, gdy widok ViewControllera został załadowany, na przykład viewDidAppear.Nie tylko application: didFinishLaunchingWithOptions:

UITextField *lagFreeField = [[UITextField alloc] init];
[self.window addSubview:lagFreeField];
[lagFreeField becomeFirstResponder];
[lagFreeField resignFirstResponder];
[lagFreeField removeFromSuperview];
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.