UIStackView 内の view を非表示にしたら、AutoLayout の警告が出る


みんな使ってるの?

UIStackView というと、Android でいう LinearLayout みたいなものなのですが、個人的に使いにくくて仕方ないです。
世の中の iOS アプリ開発してる方々は、業務でも使ってるんでしょうか?
なかなか狙ったレイアウトにできなくて、時間ばかり掛かる気がするんですが、自分が使い方ちゃんと理解してないからなのだろうか・・・。(正直、swift も業務で使われてるのか半信半疑ですが・・・)

文句ばかり書きましたが、UIStackView 内の view を非表示にすることで、Android の View.GONE みたいに、その view の分レイアウトを詰めて表示できたりするので、そういう点では便利なのかもしれません。

文句言ってないで使ってみる

慣れるために色々やってみているのですが、以下のようなパターンで警告が大量に出てしまったので、その解決策です。

大したレイアウトではないのですが、UIStackView の中に、UIImageView と UIStackView が入っています。
そして、中にある UIStackView の中に、UILabel が3つ。
ありがちといえばありがちなレイアウトだと思います。

 

UIImageView には、幅とアスペクト比の制約をつけています。
この状態で実行すると、特に警告もなく正常に表示されます。

view.hidden = YES で警告が

次に、コードで以下のようにしてみます。

- (void)viewDidLoad {
    [super viewDidLoad];
    self.imageView.hidden = YES;
}

はい、起動時に左側にある UIImageView を非表示に設定してみます。
画像が非表示になって、ラベルたちが左側によって表示される、はず。
ですが、これをやると一応正しく表示されますが、ログに以下の警告が出てきます。

2017-04-14 22:41:49.655702+0900 StackViewTest[1485:103003] [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. 
(
    "<NSLayoutConstraint:0x608000098f10 UIImageView:0x7fa4b1608aa0.width == 101   (active)>",
    "<NSLayoutConstraint:0x61000009bc60 'UISV-hiding' UIImageView:0x7fa4b1608aa0.width == 0   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x608000098f10 UIImageView:0x7fa4b1608aa0.width == 101   (active)>

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.

制約つけるの間違えたときに出てくる、あの警告ですね。
hidden を YES にしただけなのに、何が問題なんだ。

解決

imageViewの制約を、以下のようにしたところ、一応警告は出なくなりました。

幅の制約の Priority を 1000 → 999 にしました。

理屈は正直良くわかってませんw
こういうところが、UIStackView を使いにくいと感じるのかもしれません。

ちなみになのですが、この警告が起きるのは、UIStackView 内に2つ以上 view があって、左側(Axis が Vertical の場合は上側)の view に幅(Axis が Verticalの場合は高さ)の制約がついてるときのみのようです。