web-dev-qa-db-fra.com

Erreur lors de l'ajout de la vue d'entrée à textfield iOS 8

Je rencontre un problème lorsque j'ajoute une vue d'entrée personnalisée à mon application sur iOS 8. Cela fonctionnait parfaitement sur iOS 7, mais lors du passage à iOS 8, tout échoue.

Voici la trace de la pile:

2014-06-03 21:23:54.237 MyApp[1910:47245] *** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<UICompatibilityInputViewController: 0x1103f9d40>
should have parent view controller:<StopChooser: 0x11083e200> but requested parent is:<UIInputWindowController: 0x110858800>'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001042eee35 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x0000000103b919a0 objc_exception_throw + 45
    2   CoreFoundation                      0x00000001042eed6d +[NSException raise:format:] + 205
    3   UIKit                               0x00000001023d94cd -[UIViewController _addChildViewController:performHierarchyCheck:notifyWillMove:] + 184
    4   UIKit                               0x0000000102977a2b -[UIInputWindowController changeToInputViewSet:] + 416
    5   UIKit                               0x0000000102973f56 -[UIInputWindowController moveFromPlacement:toPlacement:starting:completion:] + 185
    6   UIKit                               0x000000010297826a -[UIInputWindowController setInputViewSet:] + 526
    7   UIKit                               0x0000000102973c97 -[UIInputWindowController performOperations:withAnimationStyle:] + 50
    8   UIKit                               0x00000001027559bb -[UIPeripheralHost(UIKitInternal) setInputViews:animationStyle:] + 1054
    9   UIKit                               0x0000000102422afd -[UIResponder becomeFirstResponder] + 468
    10  UIKit                               0x00000001023235d3 -[UIView(Hierarchy) becomeFirstResponder] + 99
    11  UIKit                               0x00000001029cdbfb -[UITextField becomeFirstResponder] + 51
    12  UIKit                               0x0000000102655d61 -[UITextInteractionAssistant(UITextInteractionAssistant_Internal) setFirstResponderIfNecessary] + 177
lib: terminating with uncaught exception of type NSException
    (lldb) 

La partie pertinente étant les quelques premières lignes. Quelqu'un peut-il expliquer cela? Tout ce que j'appelle c'est myTextview.inputView = keyboard; Le clavier étant un UIView créé dans le storyboard et lié via IBOutlet.

62
Milo

J'ai rencontré ce problème auparavant.

Problème:

  • Vous devez vous assurer que la vue que vous affecterez à inputView ou inputAccessoryView n'appartient à aucune vue parent. Lorsque vous créez ces vues à partir d'un xib à l'intérieur d'un ViewController, par défaut, elles sont définies en tant que sous-vues d'une vue d'ensemble.

Conseils de solution:

  • Utilisez la méthode removeFromSuperview dans la vue que vous affecterez à inputView ou inputAccessoryView
111
Tuyen Nguyen

Juste avant becomeFirstResponder supprimez la vue que vous utilisez pour l'entrée de la vue d'ensemble:

mTextField.inputView = mInputVeiw;
[mInputVeiw removeFromSuperview];
[mTextField becomeFirstResponder];

J'espère que ça aide.

18
Rudi

Vous devez vous assurer que la vue que vous affecterez à inputView ou inputAccessoryView n'appartient à aucune vue parent.

Cette erreur est particulièrement gênante car toute "vue d'entrée" créée dans un storyboard (et donc ajoutée au view du VC) ne peut pas être définie comme inputView ou inputAccessoryView sans provoquer cela crash.

Si la vue d'entrée n'est pas ajoutée au view du VC, la vue d'entrée ne sera pas disponible pour l'édition visuelle dans le Storyboard du générateur d'interface. Il n'est visible que dans le volet gauche du Storyboard.

Comment connecter la barre d'outils "Simulated Metrics" de Xcode Storyboard à une barre d'outils IBOutlet UITool?

Je préfère établir une connexion IB au inputAccessoryView directement dans le Storyboard. Cela provoque ce crash. Une solution que j'ai trouvée est de faire un IBOutlet secondaire connecté à la vue dans le Storyboard, puis dans viewDidLoad le supprimer de la super vue puis l'assigner immédiatement à inputAccessoryView. Je ne sais pas si je vais finir par l'utiliser.

- (void)viewDidLoad {

    // ...

    [self.keybordView removeFromSuperview];
    self.inputAccessoryView = self.keybordView;
}
3
pkamb

Mon problème était que j'ai nommé une vue ayant un textField 'inputAccessoryView' ...

@property (weak, nonatomic) IBOutlet CustomView *inputAccessoryView;

Erreur:

Terminating app due to uncaught exception
'UIViewControllerHierarchyInconsistency', reason: 'child view
controller:<UICompatibilityInputViewController: 0x7fed7063a1a0> should
have parent view controller:<MyViewController: 0x7fed70606f00> but
requested parent is:<UIInputWindowController: 0x7fed710cde00>'

Solution:

Vérifiez la dénomination; ne remplacez pas s'il n'est pas nécessaire.

2
Octav

Je l'ai compris. Je ne sais pas quel était le problème avant, mais au lieu de lier un UIView dans le générateur d'interface, j'ai plutôt créé un UIView par programme et cela a bien fonctionné.

2
Milo

Oui, la solution Tuyen Nguyen n'a pas fonctionné pour moi. Ce qui a fonctionné pour moi dans iOS 8/Xcode 6 pour définir un InputAccessoryView n'était pas à removeFromSuperview mais à la place:

[[UIApplication sharedApplication].keyWindow addSubview:**MyViewToBeTheUIAccessoryView**];

J'espère que ça aidera quelqu'un.

1
Sasho

J'ai eu le même problème lorsque j'ai essayé de configurer mon UIDatePicker dans mon UITextField

- (void)setupViews {
    ...
    dobField.inputView = aDatePicker; // Here was the problem
    ...
}

Ma solution, je viens "d'allouer" et "init" mon datePicker dans ViewDidLoad

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    ...
    aDatePicker = [[UIDatePicker alloc] init]; // My solution
    ...
}
1
J. Lopes

J'ai trouvé la solution créant l'UIView par programme (comme suggéré par Milo), mais elle se bloque lorsqu'elle est utilisée comme un @property. Dans mon cas, je devais créer l'instance UIPickerView dans viewDidLoad et l'assing à UITextView inputView. Quand j'ai besoin d'accéder au sélecteur, je le reçois comme ceci

UIPickerView *picker = (UIPickerView *)self.myTextField.inputView;
1
Lucio Fonseca

L'appel de removeFromSuperView dans viewDidLoad ne semble pas fonctionner correctement dans les modaux. J'ai fini par définir la vue cachée, puis la supprimer de superView dans viewDidAppear.

0
aryaxt

Ma solution pour ce problème était d'ajouter la vue à inputView, mais pas d'ajouter le contrôleur de vue au parent.

0
slobodans

La plupart des réponses que j'ai reçues étaient liées aux changements de code. J'ai découvert que la suppression d'une sortie vers l'UIView dans la vue principale le corrigeait. https://stackoverflow.com/a/40037236/46431

0
Adam Mendoza

J'ai eu la même erreur lorsque je renvoie une vue du storyboard en tant que inputAccessoryView. Je l'ai corrigé avec childViewController. Voir ma réponse ici .

0
ChikabuZ