UIStackViewがAutoLayoutのエラーになったときの対応パターン
はじめに
初登場時は機能不足が否めなかったSwiftUIも、アップデートによりUIコンポーネントが追加され、世の中のアプリでも利用されるようになりました。
しかし従来から開発が続けられているiOSアプリやSwiftUIにまだ用意されていない機能が必要な場合には未だにUIKitが現役で利用されています。
UIKitではAutoLayoutを使ってViewの配置を行うのですが、シンプルに縦、横の直線的な配置をするのにもたくさんの制約を張る必要があります。
その手間を軽減してくれるのが UIStackView で、非常によく使われるViewです。
しかし UIStackView もサイズや設定値によってはAutoLayoutがエラーを表示することがあります。
その場合にネットで解決方法を検索すると Hugging Priority や Compression Resistance Priority という2種類のpriorityを使ったものが多いです。
どっちが何だっけ?上下どちらにすればいいんだっけ?と自分が毎回悩んでしまうため、よくある配置と発生するエラーの対応方法を以下にまとめます。
前提
表示サンプル
UIStackViewのサイズ未満の場合
要素のサイズの合計が UIStackView のサイズ未満の場合、AutoLayoutが Content Priority Ambiguity などのエラーを表示します。
たとえば以下のような2つのUILabelを配置した場合です。
一見正常に配置されているように見えますが、AutoLayoutはエラーになっています。

ShortAutoLayoutError.xib
いずれかの要素のサイズを固定可能な場合
要素のサイズを固定します。
次の図では左のLabelの width を指定しました。

FixedSize.xib
要素のサイズが可変の場合
拡大を許可する要素の Content Hugging Priority を下げます。
左のLabel: 251
右のLabel: 250

UseHuggingPriority1.xib
複数の要素を配置する場合も同じです。
左のLabel: 251
中央のLabel: 250
右のLabel: 251

UseHuggingPriority2.xib
要素のサイズは可変だが拡大は防ぎたい場合
UIViewなど、ダミーのViewを配置することで要素自体はコンテンツサイズを保ちます。
たとえば次の図のように中央に配置することで、両端に寄せたレイアウトを実現することができます。

UseSpacer.xib
UIStackView のサイズより大きい場合
要素のサイズの合計が UIStackView のサイズより大きい場合も同様に、AutoLayoutが Content Priority Ambiguity などのエラーを表示します。
たとえば以下のような2つの長いテキストを持つUILabelを配置した場合です。
AutoLayoutはエラーになりますし、おそらく意図した表示ではないことも多いのではないかと思います。

LongAutoLayoutError.xib
縮小を許容できる要素が決まっている場合
縮小させる要素の Compression Resistance Priority を下げます。
左のLabel: 750
右のLabel: 749

UseCompressionResistancePriority1.xib
UILabelの折り返しが必要な場合
UILabelは numberOfLines の値を1以外に設定することで表示する行数を変更できます。
numberOfLines = 0 に設定したとき、 Compression Resistance Priority の指定だけでは折返しが適用されず、 Hugging Priority も同時に指定する必要がありました。
縮小させる要素の Compression Resistance Priority 、 Hugging Priority の両方を下げます。
左のLabel
Compression Resistance Priority: 749
Hugging Priority: 250
右のLabel
Compression Resistance Priority: 750
Hugging Priority: 251

UseCompressionResistancePriority2.xib
参考記事
Discussion