📱

UIStackViewがAutoLayoutのエラーになったときの対応パターン

2022/08/31に公開

はじめに

初登場時は機能不足が否めなかったSwiftUIも、アップデートによりUIコンポーネントが追加され、世の中のアプリでも利用されるようになりました。
しかし従来から開発が続けられているiOSアプリやSwiftUIにまだ用意されていない機能が必要な場合には未だにUIKitが現役で利用されています。

UIKitではAutoLayoutを使ってViewの配置を行うのですが、シンプルに縦、横の直線的な配置をするのにもたくさんの制約を張る必要があります。
その手間を軽減してくれるのが UIStackView で、非常によく使われるViewです。

しかし UIStackView もサイズや設定値によってはAutoLayoutがエラーを表示することがあります。
その場合にネットで解決方法を検索すると Hugging PriorityCompression Resistance Priority という2種類のpriorityを使ったものが多いです。
どっちが何だっけ?上下どちらにすればいいんだっけ?と自分が毎回悩んでしまうため、よくある配置と発生するエラーの対応方法を以下にまとめます。

前提

表示サンプル

https://github.com/kitwtnb/uistackview-priority-sample


UIStackViewのサイズ未満の場合

要素のサイズの合計が UIStackView のサイズ未満の場合、AutoLayoutが Content Priority Ambiguity などのエラーを表示します。
たとえば以下のような2つのUILabelを配置した場合です。
一見正常に配置されているように見えますが、AutoLayoutはエラーになっています。

ShortAutoLayoutError
ShortAutoLayoutError.xib

いずれかの要素のサイズを固定可能な場合

要素のサイズを固定します。
次の図では左のLabelの width を指定しました。

FixedSize
FixedSize.xib

要素のサイズが可変の場合

拡大を許可する要素Content Hugging Priority下げます。

左のLabel: 251
右のLabel: 250

UseHuggingPriority1
UseHuggingPriority1.xib

複数の要素を配置する場合も同じです。

左のLabel: 251
中央のLabel: 250
右のLabel: 251

UseHuggingPriority2
UseHuggingPriority2.xib

要素のサイズは可変だが拡大は防ぎたい場合

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

UseSpacer
UseSpacer.xib


UIStackView のサイズより大きい場合

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

LongAutoLayoutError
LongAutoLayoutError.xib

縮小を許容できる要素が決まっている場合

縮小させる要素Compression Resistance Priority下げます。

左のLabel: 750
右のLabel: 749

UseCompressionResistancePriority1
UseCompressionResistancePriority1.xib

UILabelの折り返しが必要な場合

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

左のLabel
Compression Resistance Priority: 749
Hugging Priority: 250

右のLabel
Compression Resistance Priority: 750
Hugging Priority: 251

UseCompressionResistancePriority2
UseCompressionResistancePriority2.xib


参考記事

https://qiita.com/yum_fishing/items/933e04bf40862a78e106

Discussion