¿Cómo atrapar en UIViewAlertForUnsatisfiableConstraints?

Estoy viendo un error aparecer en mi logging de depurador:

Will attempt to recover by breaking constraint <NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)> Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful. 

¿Cómo me atrapo en esa llamada? No aparece en ningún lugar de mi código.

Captura de pantalla1

¡Esta publicación me ayudó MUCHO !

Agregué el punto de corte simbólico UIViewAlertForUnsatisfiableConstraints con la acción sugerida:

Proyecto Obj-C

 po [[UIWindow keyWindow] _autolayoutTrace] 

Proyecto Swift

 expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace] 

Punto de corte simbólico con acción personalizada

Con esta pista, el logging se hizo más detallado, y fue más fácil para mí identificar qué vista tenía la restricción rota.

 UIWindow:0x7f88a8e4a4a0 | UILayoutContainerView:0x7f88a8f23b70 | | UINavigationTransitionView:0x7f88a8ca1970 | | | UIViewControllerWrapperView:0x7f88a8f2aab0 | | | | •UIView:0x7f88a8ca2880 | | | | | *UIView:0x7f88a8ca2a10 | | | | | | *UIButton:0x7f88a8c98820'Archived' | | | | | | | UIButtonLabel:0x7f88a8cb0e30'Archived' | | | | | | *UIButton:0x7f88a8ca22d0'Download' | | | | | | | UIButtonLabel:0x7f88a8cb04e0'Download' | | | | | | *UIButton:0x7f88a8ca1580'Deleted' | | | | | | | UIButtonLabel:0x7f88a8caf100'Deleted' | | | | | *UIView:0x7f88a8ca33e0 | | | | | *_UILayoutGuide:0x7f88a8ca35b0 | | | | | *_UILayoutGuide:0x7f88a8ca4090 | | | | | _UIPageViewControllerContentView:0x7f88a8f1a390 | | | | | | _UIQueuingScrollView:0x7f88aa031c00 | | | | | | | UIView:0x7f88a8f38070 | | | | | | | UIView:0x7f88a8f381e0 | | | | | | | | •UIView:0x7f88a8f39fa0, MISSING HOST CONSTRAINTS | | | | | | | | | *UIButton:0x7f88a8cb9bf0'Retrieve data'- AMBIGUOUS LAYOUT for UIButton:0x7f88a8cb9bf0'Retrieve data'.minX{id: 170}, UIButton:0x7f88a8cb9bf0'Retrieve data'.minY{id: 171} | | | | | | | | | *UIImageView:0x7f88a8f3ad80- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8f3ad80.minX{id: 172}, UIImageView:0x7f88a8f3ad80.minY{id: 173} | | | | | | | | | *App.RecordInfoView:0x7f88a8cbe530- AMBIGUOUS LAYOUT for App.RecordInfoView:0x7f88a8cbe530.minX{id: 174}, App.RecordInfoView:0x7f88a8cbe530.minY{id: 175}, App.RecordInfoView:0x7f88a8cbe530.Width{id: 176}, App.RecordInfoView:0x7f88a8cbe530.Height{id: 177} | | | | | | | | | | +UIView:0x7f88a8cc1d30- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1d30.minX{id: 178}, UIView:0x7f88a8cc1d30.minY{id: 179}, UIView:0x7f88a8cc1d30.Width{id: 180}, UIView:0x7f88a8cc1d30.Height{id: 181} | | | | | | | | | | | *UIView:0x7f88a8cc1ec0- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1ec0.minX{id: 153}, UIView:0x7f88a8cc1ec0.minY{id: 151}, UIView:0x7f88a8cc1ec0.Width{id: 154}, UIView:0x7f88a8cc1ec0.Height{id: 165} | | | | | | | | | | | | *UIView:0x7f88a8e68e10- AMBIGUOUS LAYOUT for UIView:0x7f88a8e68e10.minX{id: 155}, UIView:0x7f88a8e68e10.minY{id: 150}, UIView:0x7f88a8e68e10.Width{id: 156} | | | | | | | | | | | | *UIImageView:0x7f88a8e65de0- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e65de0.minX{id: 159}, UIImageView:0x7f88a8e65de0.minY{id: 182} | | | | | | | | | | | | *UILabel:0x7f88a8e69080'8-6-2015'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8e69080'8-6-2015'.minX{id: 183}, UILabel:0x7f88a8e69080'8-6-2015'.minY{id: 184}, UILabel:0x7f88a8e69080'8-6-2015'.Width{id: 185} | | | | | | | | | | | | *UILabel:0x7f88a8cc0690'16:34'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8cc0690'16:34'.minX{id: 186}, UILabel:0x7f88a8cc0690'16:34'.minY{id: 187}, UILabel:0x7f88a8cc0690'16:34'.Width{id: 188}, UILabel:0x7f88a8cc0690'16:34'.Height{id: 189} | | | | | | | | | | | | *UIView:0x7f88a8cc2050- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc2050.minX{id: 161}, UIView:0x7f88a8cc2050.minY{id: 166}, UIView:0x7f88a8cc2050.Width{id: 163} | | | | | | | | | | | | *UIImageView:0x7f88a8e69d90- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e69d90.minX{id: 190}, UIImageView:0x7f88a8e69d90.minY{id: 191}, UIImageView:0x7f88a8e69d90.Width{id: 192}, UIImageView:0x7f88a8e69d90.Height{id: 193} | | | | | | | | | | | *UIView:0x7f88a8f3cc00 | | | | | | | | | | | | *UIView:0x7f88a8e618d0 | | | | | | | | | | | | *UIImageView:0x7f88a8e5ba10 | | | | | | | | | | | | *UIView:0x7f88a8f3cd70 | | | | | | | | | | | | *UIImageView:0x7f88a8e58e10 | | | | | | | | | | | | *UIImageView:0x7f88a8e5e7a0 | | | | | | | | | | | | *UIView:0x7f88a8f3cee0 | | | | | | | | | | | *UIView:0x7f88a8f3dc70 | | | | | | | | | | | | *UIView:0x7f88a8e64dd0 | | | | | | | | | | | | *UILabel:0x7f88a8e65290'Average flow rate' | | | | | | | | | | | | *UILabel:0x7f88a8e712d0'177.0 ml/s' | | | | | | | | | | | | *UILabel:0x7f88a8c97150'1299.4' | | | | | | | | | | | | *UIView:0x7f88a8f3dde0 | | | | | | | | | | | | *UILabel:0x7f88a8f3df50'Maximum flow rate' | | | | | | | | | | | | *UILabel:0x7f88a8cbfdb0'371.6 ml/s' | | | | | | | | | | | | *UILabel:0x7f88a8cc0230'873.5' | | | | | | | | | | | | *UIView:0x7f88a8f3e2a0 | | | | | | | | | | | | *UILabel:0x7f88a8f3e410'Total volume' | | | | | | | | | | | | *UILabel:0x7f88a8cc0f20'371.6 ml' | | | | | | | | | | | | *UIView:0x7f88a8f3e870 | | | | | | | | | | | | *UILabel:0x7f88a8f3ea00'Time do max. flow' | | | | | | | | | | | | *UILabel:0x7f88a8cc0ac0'3.6 s' | | | | | | | | | | | | *UIView:0x7f88a8f3ee10 | | | | | | | | | | | | *UILabel:0x7f88a8f3efa0'Flow time' | | | | | | | | | | | | *UILabel:0x7f88a8cbf980'2.1 s' | | | | | | | | | | | | *UIView:0x7f88a8f3f3e0 | | | | | | | | | | | | *UILabel:0x7f88a8f3f570'Voiding time' | | | | | | | | | | | | *UILabel:0x7f88a8cc17e0'3.5 s' | | | | | | | | | | | | *UIView:0x7f88a8f3f9a0 | | | | | | | | | | | | *UILabel:0x7f88a8f3fb30'Voiding delay' | | | | | | | | | | | | *UILabel:0x7f88a8cc1380'1.0 s' | | | | | | | | | | | | *UIView:0x7f88a8e65000 | | | | | | | | | | | | *UIButton:0x7f88a8e52f20'Show' | | | | | | | | | | | | *UIImageView:0x7f88a8e6e1d0 | | | | | | | | | | | | *UIButton:0x7f88a8e52c90'Send' | | | | | | | | | | | | *UIImageView:0x7f88a8e61bb0 | | | | | | | | | | | | *UIButton:0x7f88a8e528e0'Delete' | | | | | | | | | | | | *UIImageView:0x7f88a8e6b3f0 | | | | | | | | | | | | *UIView:0x7f88a8f3ff60 | | | | | | | | | *UIActivityIndicatorView:0x7f88a8cba080 | | | | | | | | | | UIImageView:0x7f88a8cba700 | | | | | | | | | *_UILayoutGuide:0x7f88a8cc3150 | | | | | | | | | *_UILayoutGuide:0x7f88a8cc3b10 | | | | | | | UIView:0x7f88a8f339c0 | | UINavigationBar:0x7f88a8c96810 | | | _UINavigationBarBackground:0x7f88a8e45c00 | | | | UIImageView:0x7f88a8e46410 | | | UINavigationItemView:0x7f88a8c97520'App' | | | | UILabel:0x7f88a8c97cc0'App' | | | UINavigationButton:0x7f88a8e3e850 | | | | UIImageView:0x7f88a8e445b0 | | | _UINavigationBarBackIndicatorView:0x7f88a8f2b530 Legend: * - is laid out with auto layout + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES • - layout engine host 

Entonces detuve la ejecución Pausa y cambié el color de background de la vista problemática con el command …

Obj-C

 expr ((UIView *)0x7f88a8cc2050).backgroundColor = [UIColor networkingColor] 

Swift 3.0

 expr -l Swift -- import UIKit expr -l Swift -- unsafeBitCast(0x7f88a8cc2050, to: UIView.self).backgroundColor = UIColor.networking 

… y el resultado fue increíble!

Vista oculta

¡Simplemente asombroso! Espero eso ayude.

Querrá agregar un Symbolic Breakpoint . Apple proporciona una excelente guía sobre cómo hacer esto.

  1. Abre el Breakpoint Navigator cmd+7
  2. Haga clic en el button Add en la esquina inferior izquierda
  3. Seleccione Add Symbolic Breakpoint...
  4. Donde dice Symbol solo escriba UIViewAlertForUnsatisfiableConstraints

También puede tratarlo como cualquier otro punto de interrupción, activarlo o desactivarlo, agregar acciones o registrar posts.

Siguió el consejo de Stephen y trató de depurar el código y whoa! funcionó. La respuesta radica en el post de debugging en sí.

Will attempt to recover by breaking constraint NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)>

La línea de arriba le dice que el time de ejecución funcionó eliminando esta restricción. Puede ser que no necesite espacio horizontal en su button (MPKnockoutButton). Una vez que borra esta restricción, no se quejará en time de ejecución y obtendrá el comportamiento deseado.

Cada vez que bash eliminar las restricciones que el sistema tuvo que romper, mis restricciones ya no son suficientes para satisfacer el IB (es decir, las "restricciones faltantes" se muestran en el IB, lo que significa que están incompletas y no serán utilizadas). De hecho, solucioné esto estableciendo la restricción que quiere romper con la baja prioridad, lo que (y esto es una suposition) permite que el sistema rompa la restricción con gracia. Probablemente no sea la mejor solución, pero solucionó mi problema y las restricciones resultaron perfectamente.