完全に理解する Storyboard & UIKit (Day 5): Auto Layoutの複雑な制約の解決
S7r1n9y
Engineer
このシリーズの記事一覧
- 1. 完全に理解する Storyboard & UIKit (Day 1): 基礎概念と歴史
- 2. 完全に理解する Storyboard & UIKit (Day 2): XcodeでのStoryboardの基本操作
- 3. 完全に理解する Storyboard & UIKit (Day 3): UIViewControllerのライフサイクル
- 4. 完全に理解する Storyboard & UIKit (Day 4): Auto Layoutの基本原理
- 5. 完全に理解する Storyboard & UIKit (Day 5): Auto Layoutの複雑な制約の解決
- 6. 完全に理解する Storyboard & UIKit (Day 6): UIStackViewを使った効率的なレイアウト設計
- 7. 完全に理解する Storyboard & UIKit (Day 7): Size Classesによるレスポンシブデザイン
- 8. 完全に理解する Storyboard & UIKit (Day 8): Segueによる画面遷移とデータ渡し
- 9. 完全に理解する Storyboard & UIKit (Day 9): Navigation Controllerの活用
- 10. 完全に理解する Storyboard & UIKit (Day 10): Tab Bar Controllerの活用
- 11. 完全に理解する Storyboard & UIKit (Day 11): 基本的なUI部品(UILabel, UIButton, UITextField)
- 12. 完全に理解する Storyboard & UIKit (Day 12): UITextViewとキーボードハンドリング
- 13. 完全に理解する Storyboard & UIKit (Day 13): UIImageViewと画像リソース管理
- 14. 完全に理解する Storyboard & UIKit (Day 14): UIScrollViewとコンテンツのスクロール
- 15. 完全に理解する Storyboard & UIKit (Day 15): UITableViewの実装基礎
- 16. 完全に理解する Storyboard & UIKit (Day 16): UITableViewのカスタムセル作成
- 17. 完全に理解する Storyboard & UIKit (Day 17): UICollectionViewの実装基礎
- 18. 完全に理解する Storyboard & UIKit (Day 18): UICollectionViewのカスタムレイアウト
- 19. 完全に理解する Storyboard & UIKit (Day 19): Custom Viewの作成とStoryboardでの利用(@IBDesignable, @IBInspectable)
- 20. 完全に理解する Storyboard & UIKit (Day 20): アニメーションの実装(UIView Animation)
- 21. 完全に理解する Storyboard & UIKit (Day 21): Gesture Recognizerによるタッチ処理
- 22. 完全に理解する Storyboard & UIKit (Day 22): UIAlertControllerによるアラートとアクションシート
- 23. 完全に理解する Storyboard & UIKit (Day 23): UIDatePickerやUIPickerViewの実装
- 24. 完全に理解する Storyboard & UIKit (Day 24): Storyboard Referenceを用いたStoryboard分割
- 25. 完全に理解する Storyboard & UIKit (Day 25): XIBとStoryboardの使い分け・併用
- 26. 完全に理解する Storyboard & UIKit (Day 26): UIAppearanceによるアプリ全体の色・スタイル管理
- 27. 完全に理解する Storyboard & UIKit (Day 27): ダークモード対応とアセットカタログ
- 28. 完全に理解する Storyboard & UIKit (Day 28): Accessibility(VoiceOver対応など)のUI設計
- 29. 完全に理解する Storyboard & UIKit (Day 29): UIKitからSwiftUIへの移行 / UIKitでのSwiftUI利用
- 30. 完全に理解する Storyboard & UIKit (Day 30): 実践:1つのアプリをStoryboardとUIKitで完成させる
Sponsored
完全に理解する Storyboard & UIKit (Day 5): Auto Layoutの複雑な制約の解決
Day 4ではAuto Layoutの基本(X, Y, Width, Heightを確定させる)を学びました。しかし、実践では「テキストの長さによって伸び縮みするボタン」などを実装する必要があります。
ここで重要になるのが Intrinsic Content Size(自身が持っている内なるサイズ) と Priority(制約の優先度) の概念です。
1. Intrinsic Content Size とは?
Day 4で「全要素の幅と高さを確定させなければならない」と言いましたが、例えば UILabel や UIButton に対して、幅と高さの制約(Width/Height Constraint)を明示的につけなくてもエラーにならないことに気づくかもしれません。
なぜでしょうか?
それは、UILabel や UIButton、UIImageView など一部のUI要素は、中身のテキストや画像データから「自分が本来どれくらいのサイズになるべきか」をシステムに伝えることができるからです。この「中身に合わせた自然なサイズ」のことを Intrinsic Content Size と呼びます。
つまり、UILabel に対しては「X座標(Leading)」と「Y座標(Top)」の制約だけを与えれば、WidthとHeightはIntrinsic Content Sizeが自動的に適用されるため、Auto Layoutの計算が成立するのです。
2. CHCR (Content Hugging / Compression Resistance)
Intrinsic Content Sizeを持っているからといって、常にそのサイズを保てるとは限りません。例えば「赤いラベル」と「青いラベル」を横に並べて制約で画面いっぱいに広げた場合、どちらがIntrisic Content Sizeを守り、どちらが妥協して伸びたり縮んだりするのでしょうか?
それを決めるのが、CHCR と呼ばれる2つの重要なPriority(優先度)パラメータです。
Priorityは 1 ~ 1000 の数値で表されます(高い方が強い)。
Content Hugging Priority (自分が伸びないように抱きしめる力)
- 意味: 「現在の自身のサイズ(Intrinsic Content Size)よりも大きく引き伸ばされることに対する抵抗力」です。
- 例: これが高い要素は引き伸ばされにくく、低い要素が優先的に引き伸ばされて余白を埋めます。
Content Compression Resistance Priority (自分が圧縮されないように耐える力)
- 意味: 「現在の自身のサイズ(Intrinsic Content Size)よりも小さく圧縮される(文字が
...と見切れる)ことに対する抵抗力」です。 - 例: 絶対にテキストを省略したくない(全文表示させたい)ラベルは、この数値を他よりも高く(例えば
1000 (Required))設定します。
Size Inspector (⌥⌘5) の下部で設定できます。横並びの要素がエラー(Red lines)で競合している場合、大抵はこのCHCRの数値を少し調整するだけで解決します。
3. 制約の Priority (優先度)
CHCRだけでなく、我々が手動で追加したすべての制約にも Priority(初期値は 1000 = 絶対条件)が存在します。
Auto Layoutエンジンはすべての制約を満たそうと計算しますが、矛盾(競合)が発生した場合、「Priorityが低い制約を破棄して、Priorityが高い制約を守る」 という動きをします。
実践的な使い方(可変レイアウト)
例えば、「基本は画像の幅を 300 にしたい(Priority: 999)」としつつ、「親ビューの幅よりは小さくしなければならない(Priority: 1000)」という2つの制約を与えます。
画面が広いiPhoneでは 幅300 になりますが、古い小さなiPhoneでは 300 だとはみ出してしまうため、Priority 999 の制約が破棄(無視)され、画面内に収まるように自動的に縮小されます。
4. エラーの解決アプローチ
Storyboard上で赤い線やエラーマークが出たとき(Conflicting Constraints)の対処法です。
- ドキュメントアウトラインの右上にある赤い矢印アイコンをクリックして、エラー内容を読む。
- 矛盾している制約同士を見つける。
- どちらか一方の制約のPriorityを
999以下に下げる。または、等号(=)をLess Than or Equal (<=)やGreater Than or Equal (>=)に変更して許容範囲を持たせる。 - いずれかの要素の Content Hugging や Compression Resistance に微小な差をつける(例: 250 vs 251)。
📝 今日のまとめ
- Intrinsic Content Size: UILabel等が中身(テキストなど)から自動算出する自然なサイズ。
- Content Hugging Priority: 自分が「無理やり広げられる」ことへの抵抗力。
- Compression Resistance Priority: 自分が「無理やり縮められる(見切れる)」ことへの抵抗力。
- Priority(優先度): 制約同士がケンカしたときは、値の低い制約が無視される。
これでAuto Layoutの基礎理論は完璧です。どんな複雑なレイアウトも、この数式と優先度の組み合わせで作られています。 しかし、複数の要素を一直線に並べるたびに、いちいち複雑な制約を手動でつけるのは面倒ですよね。 明日の Day 6 では、Auto Layoutの苦労を劇的に減らしてくれる最強のレイアウトツール UIStackView を学びます!
このシリーズの記事一覧
- 1. 完全に理解する Storyboard & UIKit (Day 1): 基礎概念と歴史
- 2. 完全に理解する Storyboard & UIKit (Day 2): XcodeでのStoryboardの基本操作
- 3. 完全に理解する Storyboard & UIKit (Day 3): UIViewControllerのライフサイクル
- 4. 完全に理解する Storyboard & UIKit (Day 4): Auto Layoutの基本原理
- 5. 完全に理解する Storyboard & UIKit (Day 5): Auto Layoutの複雑な制約の解決
- 6. 完全に理解する Storyboard & UIKit (Day 6): UIStackViewを使った効率的なレイアウト設計
- 7. 完全に理解する Storyboard & UIKit (Day 7): Size Classesによるレスポンシブデザイン
- 8. 完全に理解する Storyboard & UIKit (Day 8): Segueによる画面遷移とデータ渡し
- 9. 完全に理解する Storyboard & UIKit (Day 9): Navigation Controllerの活用
- 10. 完全に理解する Storyboard & UIKit (Day 10): Tab Bar Controllerの活用
- 11. 完全に理解する Storyboard & UIKit (Day 11): 基本的なUI部品(UILabel, UIButton, UITextField)
- 12. 完全に理解する Storyboard & UIKit (Day 12): UITextViewとキーボードハンドリング
- 13. 完全に理解する Storyboard & UIKit (Day 13): UIImageViewと画像リソース管理
- 14. 完全に理解する Storyboard & UIKit (Day 14): UIScrollViewとコンテンツのスクロール
- 15. 完全に理解する Storyboard & UIKit (Day 15): UITableViewの実装基礎
- 16. 完全に理解する Storyboard & UIKit (Day 16): UITableViewのカスタムセル作成
- 17. 完全に理解する Storyboard & UIKit (Day 17): UICollectionViewの実装基礎
- 18. 完全に理解する Storyboard & UIKit (Day 18): UICollectionViewのカスタムレイアウト
- 19. 完全に理解する Storyboard & UIKit (Day 19): Custom Viewの作成とStoryboardでの利用(@IBDesignable, @IBInspectable)
- 20. 完全に理解する Storyboard & UIKit (Day 20): アニメーションの実装(UIView Animation)
- 21. 完全に理解する Storyboard & UIKit (Day 21): Gesture Recognizerによるタッチ処理
- 22. 完全に理解する Storyboard & UIKit (Day 22): UIAlertControllerによるアラートとアクションシート
- 23. 完全に理解する Storyboard & UIKit (Day 23): UIDatePickerやUIPickerViewの実装
- 24. 完全に理解する Storyboard & UIKit (Day 24): Storyboard Referenceを用いたStoryboard分割
- 25. 完全に理解する Storyboard & UIKit (Day 25): XIBとStoryboardの使い分け・併用
- 26. 完全に理解する Storyboard & UIKit (Day 26): UIAppearanceによるアプリ全体の色・スタイル管理
- 27. 完全に理解する Storyboard & UIKit (Day 27): ダークモード対応とアセットカタログ
- 28. 完全に理解する Storyboard & UIKit (Day 28): Accessibility(VoiceOver対応など)のUI設計
- 29. 完全に理解する Storyboard & UIKit (Day 29): UIKitからSwiftUIへの移行 / UIKitでのSwiftUI利用
- 30. 完全に理解する Storyboard & UIKit (Day 30): 実践:1つのアプリをStoryboardとUIKitで完成させる