Make a symbolic breakpoint at UI

作者: sayHellooX | 来源:发表于2017-04-05 10:45 被阅读1518次

    最近碰见了一个Auto layout的相关警告,Google了一下发现了一个很不错的方式来调试类似的bug,分享一下:
    转自:http://stackoverflow.com/questions/26389273/how-to-trap-on-uiviewalertforunsatisfiableconstraints
    利用Auto layout进行布局时容易出现以下问题,比如约束歧义,约束多余等,这时候如果我们运行程序,xcode会给在log区域输出一些警告信息,同时提供对应的查询办法,如下:

    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.
    
    

    通过上面的log我们可以知道,xcode建议我们在‘UIViewAlertForUnsatisfiableConstraints’处建立一个symbolic的断点,来调试这个问题,具体的操作如图:

    Paste_Image.png Paste_Image.png

    在symbol处填写的具体信息根据log给出的提示而定。
    其实如果我们这样做了,还是得不到具体出问题的地方在哪里,我们可以利用额外的办法,获得更加详细的信息,如图:
    如果是objc项目则输入:

    po [[UIWindow keyWindow] _autolayoutTrace]
    

    如果是swift则输入:

    expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]
    
    Paste_Image.png

    添加了这个调试之后,如果在重新运行程序,我们会看到更加详细的打印,如下:

    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
    

    在上面的log中能看见具体控件的地址等详细信息,其中有“AMBIGUOUS LAYOUT”字样的控件,就是约束存在歧义的控件,如果想找到某个有歧义的控件,可以挑选一个有歧义的空间地址,然后在lldb调试区去改变对应控件的属性值(这个办法没有亲自尝试过,因为我的问题和这个有点不一样):
    Obj-C

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

    Swift

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

    一般通过Auto layout布局出现的问题及警告,大部分是因为约束多余,或者约束歧义,只要在对应的xib中详细的查看已经添加的约束,按照横向,纵向每个方向最少两个约束的原则来排查一下,应该都能找到问题,再有一般Auto layout的问题,在程序的运行过程中,xcode会给出特别详细的问题原因,按照这些log给出的信息一般也能解决对应的问题。
    希望我的文章对你有帮助,努力,坚持,与君共勉。

    ps:最近写了一个补充版本,详见http://www.jianshu.com/p/b2ab97a3b3b8

    相关文章

      网友评论

      • 3bc336a39d20:请问如何确定AMBIGUOUS LAYOUT的问题呢?看不懂输出

      本文标题:Make a symbolic breakpoint at UI

      本文链接:https://www.haomeiwen.com/subject/qhetattx.html