LoginSignup
1
1

More than 5 years have passed since last update.

topLayoutGuideが曖昧(AMBIGUOUS)でハマるケース

Last updated at Posted at 2018-08-08

概要

謎のレイアウト崩れ。autolayoutでハマって半日以上浪費したので備忘録。

多分、autolayoutの最適化周りのバグ。view構造をバラして展開してくれるのはいいんだけど、それ故にあっちのアレが明後日の場所でエラーりましたよ、と。

結論としては、

  • navigationViewControllerのせいでまだ曖昧なとこがあるうちに
  • viewControllerのviewに貼り付けたCustomViewの中で使ってたautolayoutを解決しようとして
  • view構造を展開してから解決しようとして
  • 曖昧なままのUILayoutGuide(topLayoutGuide)との関係性が生まれ、計算しようとして、エラー。
  • エラーったから、適当に解決するね → レイアウト崩れ

ということらしく。

多分タイミングというか依存性解決に失敗してる感あるなあと、試しに
適当なタイミング(viewWillAppear:)でviewControllerに

self.view.layoutIfNeeded()

させておいたら直るという。

ほんと やめて、っていう。

状況

いつの間にか、レイアウト崩れが発生している!?
なんかよくわからんけど、autolayoutがエラーって、勝手にConstraintぶっ壊してくれる、、、
なにこれ。

2018-08-07 16:42:05.366607+0900 HogeFuga Develop[65798:3081762] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<_UILayoutSupportConstraint:0x600000286180 _UILayoutGuide:0x7f8602071450.height == 0   (active)>",
    "<_UILayoutSupportConstraint:0x6000002858c0 V:|-(0)-[_UILayoutGuide:0x7f8602071450]   (active, names: '|':UIView:0x7f8602069610 )>",
    "<NSLayoutConstraint:0x600000287df0 UIStackView:0x7f8602069800.height == 38   (active)>",
    "<NSLayoutConstraint:0x6000002871c0 V:|-(0)-[HogeFuga.THCalendarWeekdaysView:0x7f8602062bb0]   (active, names: '|':HogeFuga.THCalendarView:0x7f8602062670 )>",
    "<NSLayoutConstraint:0x600000287170 HogeFuga.THCalendarWeekdaysView:0x7f8602062bb0.height == 22   (active)>",
    "<NSLayoutConstraint:0x600000287120 V:[HogeFuga.THCalendarWeekdaysView:0x7f8602062bb0]-(0)-[UICollectionView:0x7f86038c4800]   (active)>",
    "<NSLayoutConstraint:0x6000002882a0 V:[UIStackView:0x7f8602069800]-(0)-[HogeFuga.THCalendarView:0x7f8602062670]   (active)>",
    "<NSLayoutConstraint:0x600000288340 V:[_UILayoutGuide:0x7f8602071450]-(0)-[UIStackView:0x7f8602069800]   (active)>",
    "<NSAutoresizingMaskLayoutConstraint:0x600000090c70 h=-&- v=-&- 'UIView-Encapsulated-Layout-Top' UIView:0x7f8602069610.minY == 0   (active, names: '|':UIViewControllerWrapperView:0x7f8602071d90 )>"
)
Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600000287120 V:[HogeFuga.THCalendarWeekdaysView:0x7f8602062bb0]-(0)-[UICollectionView:0x7f86038c4800]   (active)>

読むと、上から下に流れる感じの変哲のないレイアウトで、エラーる要因がない。
wtfautolayout.com とかで眺めても、どう見ても正しい。
おかしい。

まさか一番上の_UILayoutGuide:0x7f8602071450が悪いとは(ry

調べる

まずは

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.

と言われるままに
UIViewAlertForUnsatisfiableConstraintsとかいうシンボルにブレークポイントを設定。

すると、変なとこで引っかかる。

UINavigationBar:0x7fd502e0fc90
|   _UIBarBackground:0x7fd502e0c1e0
|   |   UIImageView:0x7fd502e11f60
|   |   UIVisualEffectView:0x7fd502e12190
|   |   |   _UIVisualEffectBackdropView:0x7fd502e5fa90
|   |   |   _UIVisualEffectSubview:0x7fd502e5eec0
|   _UINavigationBarLargeTitleView:0x7fd502e14020'20178月'
|   |   UILabel:0x7fd502e15390
|   _UINavigationBarContentView:0x7fd502e123f0'20178月'
|   |   *<UILayoutGuide: 0x6080001a6040 - "BackButtonGuide(0x7fd502e129e0)", layoutFrame = {{0, 0}, {24, 44}}, owningView = <_UINavigationBarContentView: 0x7fd502e123f0; frame = (0 0; 375 44); layer = <CALayer: 0x60800002bbc0>>>
|   |   *<UILayoutGuide: 0x6080001a6120 - "LeadingBarGuide(0x7fd502e129e0)", layoutFrame = {{24, 0}, {0, 44}}, owningView = <_UINavigationBarContentView: 0x7fd502e123f0; frame = (0 0; 375 44); layer = <CALayer: 0x60800002bbc0>>>- AMBIGUOUS LAYOUT for UILayoutGuide:0x6080001a6120'LeadingBarGuide(0x7fd502e129e0)'.minX{id: 610}, UILayoutGuide:0x6080001a6120'LeadingBarGuide(0x7fd502e129e0)'.Width{id: 613}
|   |   *<UILayoutGuide: 0x6080001a6200 - "TitleView(0x7fd502e129e0)", layoutFrame = {{24, 0}, {343, 44}}, owningView = <_UINavigationBarContentView: 0x7fd502e123f0; frame = (0 0; 375 44); layer = <CALayer: 0x60800002bbc0>>>- AMBIGUOUS LAYOUT for UILayoutGuide:0x6080001a6200'TitleView(0x7fd502e129e0)'.minX{id: 612}, UILayoutGuide:0x6080001a6200'TitleView(0x7fd502e129e0)'.Width{id: 616}
|   |   *<UILayoutGuide: 0x6080001a62e0 - "TrailingBarGuide(0x7fd502e129e0)", layoutFrame = {{367, 0}, {0, 44}}, owningView = <_UINavigationBarContentView: 0x7fd502e123f0; frame = (0 0; 375 44); layer = <CALayer: 0x60800002bbc0>>>- AMBIGUOUS LAYOUT for UILayoutGuide:0x6080001a62e0'TrailingBarGuide(0x7fd502e129e0)'.minX{id: 615}, UILayoutGuide:0x6080001a62e0'TrailingBarGuide(0x7fd502e129e0)'.Width{id: 619}
|   |   *<UILayoutGuide: 0x6080001a63c0 - "UIViewLayoutMarginsGuide", layoutFrame = {{16, 0}, {343, 44}}, owningView = <_UINavigationBarContentView: 0x7fd502e123f0; frame = (0 0; 375 44); layer = <CALayer: 0x60800002bbc0>>>
|   |   *UILabel:0x7fd502f42300'20178月'
|   +_UINavigationBarModernPromptView:0x7fd502e19fb0
|   |   *UILabel:0x7fd502e1a4e0

AMBIGUOUS LAYOUT for UILayoutGuideと出てるのが、autolayout的に曖昧なトコロ。

これ、どういうこと?
関係あるの?とちゃんと見比べていれば、あるいはすぐ問題解決できたかもしれません。
どゆこと?と他に理由を探したのが間違い。

わからないので、一番怪しそうなNSAutoresizingMaskLayoutConstraintを殺すべく、translatesAutoresizingMaskIntoConstraintsをfalseにしてみてくが
ViewControllerのviewにresizingMask付けなかったらダメじゃん、と、つまり違うらしい。

続いてAutolayoutGuide::デバッグに役立つヒントとかを眺めつつ
デバッガコンソールでconstraintsAffectingLayoutForAxisとかを叩くも、返ってくるのは期待してる通りの正常っぽい結果。

もはや誰が敵かわからなくなり、collectionViewだからいけないのではないか、とか
いやあるいはstoryboardのオプションが、とか色々試し出す。
混乱と疑心暗鬼。

解決

以前は動いていた、今は動いてない。
ならば、前の状況に近付けて、切り分けを、、、は面倒なので

代わりに、ばっさばっさとコメントアウトを行い、ちゃんと動く状態を作り出す。
Storyboard上で配置されてる要素を ばっさばっさと捨てながら、動くところまで持っていく。

  • 縦方向のレイアウトの問題

なのは自明だったので、それに基づいて、色々試して傾向をみる。

結果的に、上側のConstraintを切るとちゃんと動いたので、ええーっと、となり
それまで試したCompressionResistancePriorityなり
intrinsicContentSizeを設定してみたりと努力は無駄でした。ちゃんちゃん。

topLayoutGuideとかOS(ランタイム)側がよしなにしてくれるトコの認識だから
まさかそんなのが悪いとか思い付かなかったよ・・・

再現性

もう精魂果てたので、誰か暇なら再現性確認してバグレポート投げて、、、

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1