2016-07-19 5 views
0

J'ai une sous-classe UIView () qui contient un UITextView. Je veux MyView utiliser UITextView pour toutes les méthodes UIResponder comme ceci:Créer un premier UIView de répondeur en contenant un autre firstResponder (un UITextView)

@implementation MyView 

- (BOOL)canBecomeFirstResponder { 
    return _textView.canBecomeFirstResponder 
} 
- (BOOL)becomeFirstResponder { 
    return [_textView becomeFirstResponder]; 
} 
- (BOOL)canResignFirstResponder { 
    return [_textView canResignFirstResponder]; 
} 
- (BOOL)resignFirstResponder { 
    // UIResponder documentation says [super resignFirstResponder] 
    // must be called somewhere in this method 
    BOOL superResignedFirstResponder = [super resignFirstResponder]; 
    if (superResignedFirstResponder) { 
    return [_textView resignFirstResponder]; 
    } else { 
    return NO; 
    } 
} 
- (BOOL)isFirstResponder { 
    return [_textView isFirstResponder]; 
} 

@end 

Cependant, comme je lis à travers Apple's Event Delivery: The Responder Chain documentation, je pense que cela peut être une mise en œuvre incorrecte. Je ne trouve pas de documentation ou de messages sur la façon de créer un UIResponder avec un autre UIResponder.

UIKit a une notion exactement 1 firstResponder, alors quand poignées MyView-becomeFirstResponder et retourne YES, il semble raisonnable de penser UIKitMyView est le firstResponder. Cependant, puisque je appelle à son tour -[UITextView becomeFirstResponder] au sein de -[MyView becomeFirstResponder], l'un des deux doit gagner et il faut perdre. Qui gagne et qui perd? Si UITextView est le firstResponder, alors pourquoi -[MyView isFirstResponder] devrait-il retourner YES?

Quelqu'un a-t-il des conseils? Ma mise en œuvre ci-dessus est-elle correcte?

Répondre

0

Bien que j'ai trouvé other evidence that people solved this problem the same way. Cette implémentation me cause des problèmes. TLDR: Je pense que vous n'êtes pas censé composer UIResponder objets.

Mon bug:

  1. Un consommateur appelle une méthode sur MyView et appelle MyView programme -[UITextView becomeFirstResponder]. Personne ne tape sur MyViewUITextView interne.
  2. Un consommateur veut supprimer le clavier. Nous pouvons vérifier que UITextView est le firstResponder car l'API privée -[UIApplication.sharedApplication.keyWindow firstResponder] renvoie UITextView. Un consommateur appelle [UIApplication sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil], mais cet appel renvoie NO. Pendant que cet appel est effectué, UIKit n'appelle pas -[UITextView canPerformAction:withSender:] ou -[UITextView targetForAction:withSender:].

Cependant, si au lieu:

  1. l'utilisateur tape sur UITextView de MyView
  2. Un consommateur veut rejeter le clavier. Nous pouvons vérifier que UITextView est le firstResponder car l'API privée -[UIApplication.sharedApplication.keyWindow firstResponder] renvoie UITextView. Un consommateur appelle [UIApplication sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil] et cet appel renvoie YES. Alors que cet appel est fait, UIKit appelle -[UITextView canPerformAction:withSender:] et -[UITextView targetForAction:withSender:] comme prévu, puis appelle bien sûr -[UITextView resignFirstResponder], qui réussit.

je ne sais pas pourquoi, dans le premier cas [UIApplication sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil] ne délègue pas UITextView correctement, mais je dois supposer que depuis -[MyView becomeFirstResponder] sans déléguer à [super becomeFirstResponder] que les documents disent, quelque chose se foiré. Je pense que vous n'êtes pas censé composer UIResponder objets.

--EDIT--

Je ne sais toujours pas sûr de ce qui ne va pas, mais j'ai découvert que j'ai plusieurs UIWindow s dans mon application, et je l'ai entendu des gens qui savent que ™ applications multi-fenêtrées peuvent avoir des problèmes occasionnels firstResponder.