2014-09-25 12 views
7

Miałem kilka przypadków, w których testerzy zgłosili, że klawiatura zniknie, gdy zaczną pisać w niektórych polach w mojej aplikacji. Prześledziłem przepływ za pomocą symulatora i podczas debugowania na telefonie i problem nie wystąpił nigdy. Jednak kiedy próbowałem go na telefonach bez telefonu, działo się to dość konsekwentnie.Klawiatura znika sporadycznie podczas edycji z użyciem IOS 8

Oto kilka istotnych kodów. Wszystko to ma na celu ukrycie klawiatury, gdy użytkownik kliknie poza polem tekstowym. Moi UIViews są podklasy mojej klasie Touchview, który odbiera wszystkie poprawki:

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; 

}

I skonfigurowany główny widok jako widok dotykowy i uwzględniono to w widokuDodLoad:

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 

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

touchView.touchDelegate = self; 
... 
} 

Oto wdrożenie metody delegata:

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

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

To wygląda to przynajmniej zmiana w jaki reaguje na IOS 8 trafień.

+0

ja już doświadcza podobnego problemu: patrz tackoverflow.com/questions/26651384/prevent-or-detect-events-passed-on- from-ios-8-keyboard. Szczególną rzeczą jest to, że pojawia się tylko wtedy, gdy aplikacja po aplikacji przeszła na drugi plan i została ponownie przeniesiona na pierwszy plan. – Codo

+1

W moim testowaniu wszystko, co musisz zrobić, to pokazać klawiaturę, zawiesić/wznowić i pokazać klawiaturę. W tym momencie połączenia hitTest będą wykonywane na widokach za klawiaturą. Ostateczną poprawką było dodanie didShow i willHide słuchaczy i śledzenie stanu klawiatury. – gnichola

Odpowiedz

0

Problem polega na tym, że system IOS 8.0 (przynajmniej) zmienia sposób, w jaki trafienia są wysyłane do widoków. Wcześniej działania w obrębie okien klawiatury lub pól tekstowych były absorbowane i nie były przekazywane do widoku, który sprawdza się w tej aplikacji. 8.0 zmienia to i wszystkie trafienia są wysyłane.

Aby rozwiązać ten problem, ja uwięziony za oknami klawiaturowych w moim kodzie testowym hitem, a ja porównał hitView do textField widoki do filtrowania tych out:

Touchview.m ma teraz następujące. Metoda keyboardView przystosowany jest z tego przepełnienie stosu odpowiedź: 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; 
} 

Nowa metoda delegat:

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

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

metoda firstResponder jest z tego GIST: https://gist.github.com/vilanovi/e52face5c6f00ce5254d

+0

hitTest nie zostaje wyrzucony, gdy moja klawiatura jest podsłuchiwana? dla reszty widoku zostaje wyrzucony, gdy dotknąłem klawiatury. Jakieś rozwiązanie tego? –

0

ustalona w iOS 8.0.2 Nie jest już konieczne.

+0

ten problem nadal istniał dla mnie w 8.1 – Fluffhead

0

To nadal dzieje się w 8,02 mi

+0

Skończyło się na ratowaniu w hitTest. Zawsze tworzyło niewiarygodne wyniki. Czasami delegują będą strzelać dwa razy z kranu, a czasem 3 razy. Czasami nadawca był znaną klasą, czasami był klasą wewnętrzną i często nie korelował z rzeczywistym dotkniętym obiektem. HitTest wydaje się być zepsuty. Zmieniłem implementację, aby korzystać z guestureRecognizers i działa dobrze. –

0

zauważyłem ten sam problem - klawiatura zostanie odwołany, gdy użytkownik próbuje wpisać na nim.

Moje rozwiązanie to obejście tego problemu. Aby rozwiązać problem, tworzę puste puste UIView pod klawiaturą. Ten sztuczny widok pochłania i pochłania zdarzenia związane z dotknięciem, a klawiatura nie jest odrzucana. Tworzę widok na "UIKeyboardDidShowNotification" i usuwam go z "UIKeyboardWillHideNotification". To pozbywa się problemu i działa dobrze ze zmianami orientacji ekranu.

Oto kod moim zdaniem kontrolera, który zawiera pola tekstowe, które pojawiają się na klawiaturze:

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

w metodzie viewDidLoad rejestrujemy na klawiaturze pokazać/ukryć powiadomienia:

// 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]; 

Następnie, po otrzymaniu powiadomienia "pokazanego na klawiaturze", utworzymy fikcyjny widok pod klawiaturą:

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

... i usunąć go, gdy klawiatura jest ukryta:

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