2014-09-25 9 views
7

Ho avuto diversi casi in cui i tester hanno segnalato che la tastiera spariva ogni volta che iniziarono a digitare in alcuni campi della mia app. Ho tracciato il flusso utilizzando il simulatore e durante il debug su un telefono e il problema non si è verificato, mai. Tuttavia, quando l'ho provato su un telefono senza fili è successo in modo abbastanza coerente.La tastiera scompare a intermittenza quando si modifica utilizzando IOS 8

Ecco un codice pertinente. Tutto questo per nascondere la tastiera quando un utente tocca un campo di testo. I miei UIViews sono sottoclassi della mia classe TouchView, che riceve tutti i tocchi:

TouchView.h:

@protocol TouchViewDelegate <NSObject> 

-(UIView *) handleTouches:(NSSet *)touches withEvent:(UIEvent *)event inView:(UIView *) view; 

@end 

@interface TouchView : UIScrollView 

@property (nonatomic, strong) id <TouchViewDelegate> touchDelegate; 

@end 

TouchView.m:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 
    UIView * touchedView = [super hitTest:point withEvent:event]; 
    NSSet* touches = [event allTouches]; 
    [self.touchDelegate handleTouches:touches withEvent:event inView:touchedView]; 
    return touchedView; 

}

ho configurato vista principale come touchview e incluso nel viewDidLoad:

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 

HMWTouchView * touchView = (HMWTouchView*) self.view; 

touchView.touchDelegate = self; 
... 
} 

Ecco un'implementazione del metodo delegato:

-(UIView *) handleTouches:(NSSet *)touches withEvent:(UIEvent *)event inView:(UIView *) hitView { 

if (![hitView isKindOfClass:[UIButton class]]) { 
    [[UIResponder firstResponder] resignFirstResponder]; 
} 
return self.view; 
} 

Questo appare come è almeno un cambiamento nel modo in cui IOS 8 risponde ai colpi.

+0

ho sperimenta un problema simile: vedi tackoverflow.com/questions/26651384/prevent-or-detect-events-passed-on- da-ios-8-tastiera. La cosa particolare è: si verifica solo se l'app dopo l'app è passata allo stato di sfondo e portata nuovamente in primo piano. – Codo

+1

Nei miei test tutto ciò che dovete fare è mostrare la tastiera, sospendere/riprendere e mostrare la tastiera. A quel punto, le chiamate hitTest verranno effettuate su visualizzazioni dietro la tastiera. La mia soluzione finale era aggiungere gli ascoltatori didShow e willHide e tenere traccia dello stato della tastiera da solo. – gnichola

risposta

0

Il problema è che IOS 8.0 (almeno) modifica il modo in cui gli hit vengono inviati alle viste. In precedenza, i colpi all'interno di finestre di tastiera o campi di testo venivano assorbiti e non trasmessi all'hitview, che funziona bene per questa applicazione. 8.0 cambia questo e tutti gli hit vengono inviati.

Per risolvere questo problema, ho intrappolato per le finestre di tastiera all'interno del mio codice di hit testing, e io rispetto la hitView al campo di testo di vista per filtrare quelli fuori:

Touchview.m ora ha la seguente. Il metodo keyboardView è adattato a questa risposta Stack Overflow: iOS: How to access the `UIKeyboard`?

-(UIView *) keyboardView { 
//Return the current keyboard view 
UIWindow * keyboardWindow; 

UIView* keyboardView; 

UIView* primaryKeyboardView; 

for (UIWindow *window in [[UIApplication sharedApplication] windows]) 
{ 
    if ([NSStringFromClass([window class]) isEqualToString:@"UITextEffectsWindow"]) 
    { 
     keyboardWindow = window; 
     break; 
    } 
} 

for(int i = 0 ; i < [keyboardWindow.subviews count] ; i++) 
{ 
    keyboardView = [keyboardWindow.subviews objectAtIndex:i]; 
    // keyboard found, add the button 

    if([[keyboardView description] hasPrefix:@"<UIPeripheralHost"] == YES){ 
     primaryKeyboardView = keyboardView; 
    } 
    //This code will work on iOS 8.0 
    else if([[keyboardView description] hasPrefix:@"<UIInputSetContainerView"] == YES){ 

     for(int i = 0 ; i < [keyboardView.subviews count] ; i++) 
     { 
      UIView* hostkeyboard = [keyboardView.subviews objectAtIndex:i]; 

      if([[hostkeyboard description] hasPrefix:@"<UIInputSetHost"] == YES){ 
       primaryKeyboardView = hostkeyboard; 
      } 
     } 
    } 
} 
return primaryKeyboardView; 
} 

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 
UIView * touchedView = [super hitTest:point withEvent:event]; 
NSSet* touches = [event allTouches]; 
UIView * keyboardView = [self keyboardView]; 
if (touchedView != keyboardView) { //Ignore the hit if it's a keyboard 
    [self.touchDelegate handleTouches:touches withEvent:event inView:touchedView]; 
} 
return touchedView; 
} 

il nuovo metodo delegato:

-(UIView *) handleTouches:(NSSet *)touches withEvent:(UIEvent *)event inView:(UIView *) hitView { 

if (![hitView isKindOfClass:[UIResponder class]]) { 
    [[UIResponder firstResponder] resignFirstResponder]; 
} 
return hitView; 
} 

il metodo firstResponder è da questa sostanza: https://gist.github.com/vilanovi/e52face5c6f00ce5254d

+0

hitTest non viene generato mentre viene toccata la mia tastiera? per il resto della vista, viene colpito quando tocco fuori dalla tastiera. Qualche soluzione per quello? –

0

fisso in IOS 8.0.2 Non è più necessario.

+0

questo problema esisteva ancora per me in 8.1 – Fluffhead

0

Questo accade ancora in 8,02 per me

+0

ho finito per il salvataggio su hitTest. Ha sempre prodotto risultati inaffidabili. A volte delegano a sparare due volte per rubinetto, e talvolta per 3 volte. A volte il mittente era una classe nota, a volte era una classe interna e spesso non era correlata all'oggetto reale toccato. HitTest sembra essere rotto. Ho cambiato la mia implementazione per usare guestureRecognizers e funziona perfettamente. –

0

ho osservato lo stesso problema - la tastiera viene respinto quando l'utente tenta di digitare su di esso.

La mia soluzione è una soluzione alternativa. Per risolvere il problema, creo un UIView vuoto fittizio sotto la tastiera. Questa vista fittizia assorbe e consuma eventi tap e la tastiera non viene ignorata. Creo la vista su "UIKeyboardDidShowNotification" e la rimuoverò su "UIKeyboardWillHideNotification". Questo elimina il problema e funziona bene con i cambiamenti di orientamento dello schermo.

Ecco il codice a mio controller della vista che contiene i campi di testo che mostrano la tastiera:

/** Dummy view placed underneath the keyboard to prevent its dismissal. */ 
@property(nonatomic, strong) UIView *dummyView; 

Nel metodo viewDidLoad registriamo per tastiera mostra/nascondi le notifiche:

// keyboard notifications - we need this to prevent keyboard dismissal 
[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(keyboardWasShown:) 
              name:UIKeyboardDidShowNotification object:nil]; 

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(keyboardWillBeHidden:) 
              name:UIKeyboardWillHideNotification object:nil]; 

poi, dopo aver ricevuto la 'tastiera mostrati' notifica creiamo la vista fittizia sotto la tastiera:

- (void)keyboardWasShown:(NSNotification*)notification { 
    // we need this to prevent keyboard dismissal  
    NSDictionary* info = [notification userInfo]; 
    CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
    keyboardFrame = [self.view convertRect:keyboardFrame fromView:nil]; 
    self.dummyView = [[UIView alloc] initWithFrame:keyboardFrame]; 
    [self.view addSubview:self.dummyView]; 
} 

... e rimuoverlo quando la tastiera è nascosta:

- (void)keyboardWillBeHidden:(NSNotification*)notification { 
    [self.dummyView removeFromSuperview]; 
    self.dummyView = nil; 
}