ios crash uialertcontroller ios8.3

El UIAlertController de iOS 8.3 se bloquea al intentar agregar un campo de texto



crash ios8.3 (12)

Acabo de ejecutar su código dentro de mi proyecto de prueba: todo funcionó bien en 8.3.

View not found in container hierarchy:

Este error suele aparecer si se estropea la relación hijo / padre de UIViewController. Hay algunos puntos a considerar:

  • El controlador que está utilizando para presentar la alerta es el más alto y no presenta nada más.
  • los controladores principales tienen el que usas como hijo ( addChildViewController: o están en estado de presentarlos a través de presentViewController:animated:completion: o presentViewController:animated:completion:
  • La vista del controlador se carga antes de presentar otro ViewController.

Además, definitivamente hay algo mal con los marcos.

Tengo una aplicación para iPad. Estoy creando un UIAlertController y agregando un campo de texto. Se estrella Solo se bloquea cuando agrego un campo de texto.

let alert = UIAlertController(title: "Enter Name", message:nil, preferredStyle: UIAlertControllerStyle.Alert); alert.addTextFieldWithConfigurationHandler { (textfield:UITextField!) -> Void in textfield.placeholder = "Sexy time"; } alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: {(action:UIAlertAction!) -> Void in //Some action here })); self.presentViewController(alert, animated: true, completion: nil);

Tengo un choque divertido que me dice que las restricciones están en mal estado. Este código funciona bien en <8.3 sin advertencias. Incluso en un proyecto limpio que no contiene nada más que este código, se bloquea: el proyecto debe ser un proyecto de vista dividida en iPad.

Aquí está el seguimiento completo de la pila más advertencias de restricciones extrañas que aparecen solo después de intentar agregar el campo de texto a alertController.

2015-04-10 15:25:07.155 Observation[18235:281813] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fb66cf9dfc0 UITableView:0x7fb66b855000.left == UIView:0x7fb66fae68e0.left> When added to a view, the constraint''s items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug. 2015-04-10 15:25:07.155 Observation[18235:281813] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fb66cf9e010 UITableView:0x7fb66b855000.right == UIView:0x7fb66fae68e0.right> When added to a view, the constraint''s items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug. 2015-04-10 15:25:07.155 Observation[18235:281813] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fb66fb37f90 UITableView:0x7fb66b855000.top == UIView:0x7fb66fae68e0.top> When added to a view, the constraint''s items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug. 2015-04-10 15:25:07.156 Observation[18235:281813] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fb66fb80580 UITableView:0x7fb66b855000.bottom == UIView:0x7fb66fae68e0.bottom> When added to a view, the constraint''s items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug. 2015-04-10 15:25:13.589 Observation[18235:281813] View hierarchy unprepared for constraint. Constraint: <NSLayoutConstraint:0x7fb66cf9dfc0 UITableView:0x7fb66b855000.left == UIView:0x7fb66fae68e0.left> Container hierarchy: <UIView: 0x7fb66fa86e00; frame = (0 0; 0 0); layer = <CALayer: 0x7fb66fadf8e0>> | <UIView: 0x7fb66af3e080; frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0x7fb66fae32c0>> | | <_UIAlertControllerShadowedScrollView: 0x7fb66fa68c80; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7fb66fa38a80>; layer = <CALayer: 0x7fb66fa97560>; contentOffset: {0, 0}; contentSize: {0, 0}> | | | <UIView: 0x7fb66fa87350; frame = (0 0; 0 0); layer = <CALayer: 0x7fb66fadf810>> | | | | <UILabel: 0x7fb66fa88740; frame = (0 0; 0 0); text = ''Enter Name''; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fb66fa94ed0>> | | | | <UILabel: 0x7fb66fa73710; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fb66cc0ee10>> | | | | <UIView: 0x7fb66fae68e0; frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0x7fb66fa90160>> | | <UILabel: 0x7fb66fa3ad40; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fb66fa73680>> | | <UICollectionView: 0x7fb66c130200; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7fb66faebab0>; layer = <CALayer: 0x7fb66fa3acf0>; contentOffset: {0, 0}; contentSize: {0, 0}> collection view layout: <_UIAlertControllerCollectionViewFlowLayout: 0x7fb66fae0b30> View not found in container hierarchy: <UITableView: 0x7fb66b855000; frame = (0 20; 768 1004); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fb66cf79f30>; layer = <CALayer: 0x7fb66cf600a0>; contentOffset: {0, 0}; contentSize: {768, 25}> That view''s superview: NO SUPERVIEW 2015-04-10 15:25:13.594 Observation[18235:281813] *** Terminating app due to uncaught exception ''NSGenericException'', reason: ''Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That''s illegal. constraint:<NSLayoutConstraint:0x7fb66cf9dfc0 UITableView:0x7fb66b855000.left == UIView:0x7fb66fae68e0.left> view:<UIView: 0x7fb66fa86e00; frame = (0 0; 0 0); layer = <CALayer: 0x7fb66fadf8e0>>'' *** First throw call stack: ( 0 CoreFoundation 0x0000000102940c65 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x000000010221dbb7 objc_exception_throw + 45 2 CoreFoundation 0x0000000102940b9d +[NSException raise:format:] + 205 3 Foundation 0x0000000101daf479 -[NSLayoutConstraint _addToEngine:integralizationAdjustment:mutuallyExclusiveConstraints:] + 187 4 UIKit 0x00000001039bca34 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke_2 + 474 5 Foundation 0x0000000101dbd1be -[NSISEngine withBehaviors:performModifications:] + 155 6 UIKit 0x00000001039bc83a __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 452 7 UIKit 0x00000001039bc64d -[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 197 8 UIKit 0x00000001039bc933 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke_2 + 217 9 Foundation 0x0000000101dbd1be -[NSISEngine withBehaviors:performModifications:] + 155 10 UIKit 0x00000001039bc83a __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 452 11 UIKit 0x00000001039bc64d -[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 197 12 UIKit 0x00000001039bc933 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke_2 + 217 13 Foundation 0x0000000101dbd1be -[NSISEngine withBehaviors:performModifications:] + 155 14 UIKit 0x00000001039bc83a __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 452 15 UIKit 0x00000001039bc64d -[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 197 16 UIKit 0x00000001033b5717 __40-[UIView(Hierarchy) layoutBelowIfNeeded]_block_invoke + 39 17 Foundation 0x0000000101dbd1be -[NSISEngine withBehaviors:performModifications:] + 155 18 UIKit 0x00000001033b5556 -[UIView(Hierarchy) layoutBelowIfNeeded] + 320 19 UIKit 0x000000010374a394 -[_UIAlertControllerAnimatedTransitioning animateTransition:] + 470 20 UIKit 0x000000010344fa4e __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 1867 21 UIKit 0x000000010336562c _applyBlockToCFArrayCopiedToStack + 314 22 UIKit 0x00000001033654a6 _afterCACommitHandler + 533 23 CoreFoundation 0x0000000102873ca7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 24 CoreFoundation 0x0000000102873c00 __CFRunLoopDoObservers + 368 25 CoreFoundation 0x0000000102869a33 __CFRunLoopRun + 1123 26 CoreFoundation 0x0000000102869366 CFRunLoopRunSpecific + 470 27 GraphicsServices 0x0000000106dd6a3e GSEventRunModal + 161 28 UIKit 0x0000000103341900 UIApplicationMain + 1282 29 Observation 0x0000000101612927 main + 135 30 libdyld.dylib 0x0000000104f60145 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException


Aha, creo que esto puede ser respondido por jcesarmobile en otro hilo: UIAlertController / UIAlertView scrolling en iOS 8

La solución que muchos usuarios agregaron para lidiar con errores anteriores con texto largo en UIAlertController ahora causa este bloqueo en 8.3. Y el problema del texto largo se ha corregido en 8.3, por lo que la solución puede hacerse condicional para evitar esto en 8.3


Como mencionó @Dex, lo arreglé modificando la vista de mi controlador DESPUÉS de agregar el campo de texto. Estaba modificando el tinte de la vista.

controller.view.tintColor = ...some color...

Mover esto a "después" agregando el campo de texto lo arreglé para mí La respuesta aceptada y otras sugerencias me llevaron a otros errores. Lo sentimos, no tengo el representante para publicar un comentario todavía en la respuesta de @Dex.


Este error se desencadena si la vista UIAlertController se carga cuando llama a -addTextFieldWithConfigurationHandler: ( [alert isViewLoaded] == YES ).

Si está accediendo a alert.view antes de llamar a -addTextFieldWithConfigurationHandler, mueva lo que esté haciendo con alert.view después de la llamada a -addTextFieldWithConfigurationHandler:


Esto lo arreglé de inmediato (para mí). Tuve exactamente el mismo error que Chris describió:

NSInteralInconsistencyException - UIKeyboardLayoutAlignmentView

La respuesta fue simplemente asegurarse de que la animación esté configurada en "NO" al presentar el UIAlertController.

[self presentViewController:alert animated:NO completion:nil];


Esto parece tener algo que ver con el estilo de la vista del controlador UIAlertController, como eludió @BigShay.

En mi ejemplo, establezco el tintColor de la vista antes de agregar el UITextField y me coloco en iOS 8. La solución que da @ Baza207 para agregar el UITextField después de mostrar la alerta evita el bloqueo en iOS 8, sin embargo, tampoco produce un campo de texto Apareciendo en absoluto en iOS 9.

Si solo mueve el estilo después de agregar el campo de texto, funciona con iOS 8 y iOS 9 (no se bloquea en iOS 8 y no falta el campo de texto en iOS 9):

Crash en iOS 8

Funciona en iOS 9

alertController.view.tintColor = UIColor.blueColor() alertController.addTextFieldWithConfigurationHandler { textField in } presentViewController(alertController, animated: true, completion: nil)

Funciona en iOS 8

No hay campo de texto de texto en iOS 9

alertController.view.tintColor = UIColor.blueColor() presentViewController(alertController, animated: true, completion: nil) alertController.addTextFieldWithConfigurationHandler { textField in }

Funciona en iOS 8

Funciona en iOS 9

alertController.addTextFieldWithConfigurationHandler { textField in } alertController.view.tintColor = UIColor.blueColor() presentViewController(alertController, animated: true, completion: nil)


Parece que hay un error en las alertas relacionadas con iOS 8.3. Se manifiesta tanto en UIAlertView (en desuso) como en UIAlertController solo para iOS8. Cuando intento agregar un campo de texto a cualquiera de estos controladores, obtengo el siguiente bloqueo:

*** Terminating app due to uncaught exception ''NSInternalInconsistencyException'', reason: ''The layout constraints still need update after sending -updateConstraints to <_UIKeyboardLayoutAlignmentView: 0x792d28e0; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x792d2ab0>>. _UIKeyboardLayoutAlignmentView or one of its superclasses may have overridden -updateConstraints without calling super. Or, something may have dirtied layout constraints in the middle of updating them. Both are programming errors.''

Las alertas sin campos de texto están bien, pero mostrar un UIAlertView con estilo UIAlertViewStylePlainTextInput o mostrar un UIAlertController con un campo de texto agregado mediante addTextFieldWithConfigurationHandler dará lugar a la falla anterior.

La solución parece ser establecer un marco profiláctico en el UIAlertController antes de llamar a show. Este marco se anula antes de mostrar, pero evita el bloqueo.

if (NSClassFromString(@"UIAlertController")) { // iOS8 UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Be alert, not alarmed" preferredStyle:UIAlertControllerStyleAlert]; [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { textField.keyboardType = UIKeyboardTypeEmailAddress; }]; alert.view.frame = CGRectMake(0.0, 0.0, 320.0, 400.0); // Workaround iOS8.3 bug - set this to larger than you''ll need [self presentViewController:alert animated:YES completion:^{ [alert.textFields[0] becomeFirstResponder]; }]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Be alert, not alarmed" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; alert.alertViewStyle = UIAlertViewStylePlainTextInput; UITextField *emailField = [alert textFieldAtIndex:0]; emailField.keyboardType = UIKeyboardTypeEmailAddress; [alert show]; }


Realmente no me gustaron las soluciones que vi y se me ocurrió una más fácil. El bloqueo se produce (al menos para mí) cuando el teclado está visible y se presenta una alerta con un campo de entrada.

Simplemente descarto el teclado antes de presentar la alerta y luego todo está bien.


Tengo el mismo problema con el nuevo iOS 8.3 y Swift 1.2. UIAlertController en UIViewController con UITableView anidado no funciona como en el tema de inicio.

Entonces, hice una forma modal real.

  1. Cree un nuevo ancho de UIViewController, configure el fondo de las vistas en negro con una opacidad de 0.4
  2. Agregue un UIView de 300x150 con dos botones, etiqueta y UITextField
  3. Añadir restricciones y otro personal necesario
  4. Conecta modalmente otros controladores con el nuevo.
  5. Y especifique la clase especial para el nuevo controlador como "PopupWindow". Entonces crea esta clase:

    import UIKit class PopupWindow: UIViewController, UITextFieldDelegate { @IBOutlet var wrapper: UIView! @IBOutlet var btnCancel: UIButton! @IBOutlet var btnSave: UIButton! @IBOutlet var textField: UITextField! @IBOutlet var labelField: UILabel! var keyboardHeight: CGFloat = 0 var data = [:] var closure: ((textField: UITextField!) -> Void)? var tmpText = "" override func viewDidLoad() { super.viewDidLoad() self.labelField.text = self.data["title"] as? String self.textField.text = self.data["text"] as? String self.btnCancel.setTitle("cancel", forState: UIControlState.Normal) var tmp = self.data["save"] != nil ? self.data["save"] as! String : "save" self.btnSave.setTitle(tmp, forState: UIControlState.Normal) self.btnSave.enabled = false self.wrapper.layer.cornerRadius = 5.0 as CGFloat self.textField.becomeFirstResponder() } @IBAction func onBtnCancel() { self.dismissViewControllerAnimated(true, completion: nil) } @IBAction func onBtnSave() { if self.closure != nil { self.dismissViewControllerAnimated(true, completion: { _ in self.closure!(textField: self.textField) }) } } override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) { self.fixTopOffset() } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) NSNotificationCenter.defaultCenter().addObserver(self, selector: "textFieldDidChange:", name: UITextFieldTextDidChangeNotification, object: self.textField) NSNotificationCenter.defaultCenter().addObserver(self, selector: "onKeyboadWillShow:", name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "onKeyboadWillShow:", name: UIKeyboardWillChangeFrameNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "onKeyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil) } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextFieldTextDidChangeNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillChangeFrameNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) } func onKeyboadWillShow(notification: NSNotification) { self.fixTopOffset() let info: NSDictionary = notification.userInfo! if let rectValue = info[UIKeyboardFrameBeginUserInfoKey] as? NSValue { let kbSize: CGRect = rectValue.CGRectValue() if self.keyboardHeight != kbSize.size.height { self.keyboardHeight = kbSize.size.height self.fixTopOffset() } } } func onKeyboardWillHide(notification: NSNotification) { self.fixTopOffset() if self.keyboardHeight != 0 { self.keyboardHeight = 0 self.fixTopOffset() } } func fixTopOffset(landscape: Bool = true) { let height1: CGFloat = self.view.frame.height / 2 let height2: CGFloat = height1 - self.keyboardHeight / 2 let margin: CGFloat = height1 - height2 for tmp in self.view.constraints() { if let constraint = tmp as? NSLayoutConstraint { if constraint.firstAttribute == NSLayoutAttribute.CenterY { if constraint.constant != margin { constraint.constant = margin } } } } } func textFieldDidChange(notification: NSNotification) { if notification.object != nil { if let textField = notification.object as? UITextField { self.btnSave.enabled = textField.text != self.tmpText } } } }

Debe conectar todos los IBOutlets con los elementos correspondientes a la vista mediante Ctrl + Arrastrar.

  1. Y ahora puedes usar la ventana en cualquier controlador conectado. Por ejemplo:

    import UIKit class ExampleView: UIViewController { override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "showPopup" { if let controller = segue.destinationViewController as? PopupWindow { controller.data = sender as! NSDictionary // This action will be called after form submission // We just print text in console controller.closure = { (textField: UITextField!) in println(textField) } } } } func showPopupWindow() { let data = [ "title": "My Window", "save": "Save", "text": "Do you realy want to save this text?", ] self.performSegueWithIdentifier("showPopup", sender: data) } }

Ahora puedo agregar un segmento al controlador y escribir cualquier cierre en el método prepareSegue, ¡y funciona!

Hice un video corto con una ventana emergente en mi aplicación - http://youtu.be/JmqAAeUN-XU


Trate de establecer alert.view.frame explícitamente a algo pequeño. Creo que, por defecto, puede ser tan grande como la vista de la aplicación, activando esto en sus subvistas.


Tuve un problema similar que también se menciona en los comentarios. Por favor vea esto si está recibiendo.

*** Finalización de la aplicación debido a la excepción no detectada ''NSInternalInconsistencyException'', razón: ''Las restricciones de diseño aún necesitan actualización después de enviar -updateConstraints a <_UIKeyboardLayoutAlignmentView: 0x792d28e0; marco = (0 0; 0 0); userInteractionEnabled = NO; capa =>. _UIKeyboardLayoutAlignmentView o una de sus superclases puede haber anulado -updateConstraints sin llamar a super. O bien, algo puede tener restricciones de diseño sucias en medio de actualizarlas. Ambos son errores de programación.

NSInteralInconsistencyException - UIKeyboardLayoutAlignmentView


Edición: esta corrección cambia dependiendo de si está compilando con Xcode 6 o Xcode 7, así que he agregado la información relevante para ambas versiones de Xcode.

Me encontré con esto hoy y lo que está diciendo es que no puede agregar el campo de texto a la vista del controlador de vista o que no puede agregar restricciones de diseño automático a su supervisión. Esto parece ser porque no ha creado la vista de supervisión para agregarla todavía, y por lo tanto todo entra en pánico y se bloquea.

La solución simple que encontré es agregar el campo de texto después de decirle al controlador de alerta que presente. Eso me lo arregló, aunque no estoy seguro de si afectará algo como el campo de texto que aparece cuando se presenta la alerta.

Construido con Xcode 6

let alertController = UIAlertController(title: "Enter Name", message:nil, preferredStyle: .Alert) let okAction = UIAlertAction(title: "Ok", style: .Default) { (_) -> Void in // Some action here } alertController.addAction(okAction) presentViewController(alertController, animated: true, completion: nil) // Add any text fields after presenting the alert controller to fix crash in iOS 8.3 alertController.addTextFieldWithConfigurationHandler { (textfield) -> Void in textfield.placeholder = "Name" }

Ps Como una nota al margen de su ejemplo de código, recuerde que con Swift no necesita usar ; al final de cada línea, aunque no importa si lo haces. 😉

Construido con Xcode 7

Cuando creas tu aplicación con Xcode 7, parece que Apple solucionó el problema. El uso del método que se muestra arriba ya no mostrará un campo de texto en iOS 9 (aunque aún se muestre correctamente en iOS 8).

A continuación se muestra un fragmento de código, cómo debería haber sido todo el tiempo, y cuando está integrado en Xcode 7, se ejecuta correctamente en iOS 8 y iOS 9.

let alertController = UIAlertController(title: "Enter Name", message:nil, preferredStyle: .Alert) alertController.addTextFieldWithConfigurationHandler { (textfield) -> Void in textfield.placeholder = "Name" } let okAction = UIAlertAction(title: "Ok", style: .Default) { (_) -> Void in // Some action here } alertController.addAction(okAction) presentViewController(alertController, animated: true, completion: nil)

Probado en Swift 2.0 y Obj-C con Xcode 7 GM (7A218)