プログラムによる制約の作成
可能な場合はいつでも、Interface Builder を使用して制約を設定してください。Interface Builder は、制約を視覚化し、編集し、管理し、およびデバッグするための幅広いツールを提供します。制約を分析することにより、設計時に多くの一般的なエラーを明らかにし、アプリが実行される前に問題を見つけて修正できるようにします。
Interface Builder は、増え続けるタスクを管理できます。ほとんどすべての型の制約を Interface Builder で直接ビルドできます (Interface Builder での制約の操作 を参照の事)。サイズクラス固有の制約を指定することもでき (自動レイアウトのデバッグ を参照の事)、スタックビューのような新しいツールを使用して、実行時にビューを動的に追加または削除することもできます (動的スタックビュー を参照の事)。ただし、ビュー階層に対する動的な変更の一部は、コードでのみ管理できます。
プログラムで制約を作成する場合、3 つの選択肢があります。レイアウトアンカーを使用するか、NSLayoutConstraint クラスを使用するか、または 視覚書式言語を使用できます。
レイアウトアンカー
NSLayoutAnchor クラスは、制約を作成するための流暢なインターフェイスを提供します。この API を使用するには、制約すべき項目のアンカープロパティにアクセスします。たとえば、ビューコントローラの上下のレイアウトガイドには、topAnchor、bottomAnchor、heightAnchor プロパティがあります。一方、ビューは、その端、中心、サイズ、およびベースラインのアンカーを公開します。
iOS では、ビューにも layoutMarginsGuide プロパティと readibleContentGuide プロパティがあります。 これらのプロパティは、ビューのマージンと読みやすいコンテンツガイドをそれぞれ表す UILayoutGuide オブジェクトを公開します。次に、これらのガイドは、端、中心、およびサイズのアンカーを公開します。
プログラムでマージンに、または読みやすいコンテンツガイドに制約を作成する場合は、これらのガイドを使用してください。
レイアウトアンカーを使用すると、読みやすくコンパクトな形式で制約を作成できます。リスト 13-1 に示すように、これらはさまざまな型の制約を作成するためのいくつかのメソッドを公開しています。
リスト 13-1 レイアウトアンカーの作成
1 // Get the superview's layout 2 let margins = view.layoutMarginsGuide 3 4 // Pin the leading edge of myView to the margin's leading edge 5 myView.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true 6 7 // Pin the trailing edge of myView to the margin's trailing edge 8 myView.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true 9 10 // Give myView a 1:2 aspect ratio 11 myView.heightAnchor.constraint(equalTo: myView.widthAnchor, multiplier: 2.0).isActive = true
制約の構造 で説明したように、制約は単なる線形方程式です。
レイアウトアンカーには、制約を作成するためのいくつかの異なる方法があります。各メソッドには、結果に影響を与える方程式の要素のパラメータのみが含まれます。したがって、以下のコード行で:
記号は、方程式の以下の部分に対応しています。
方程式 | 記号 |
項目 1 | myView |
属性 1 | LeadingAnchor |
関係 | constraintEqualToAnchor |
乗数 | なし (デフォルトは 1.0) |
項目 2 | margins(マージン) |
属性 2 | leadingAnchor |
定数 | なし (デフォルトは 0.0) |
レイアウトアンカーはまた、追加の型安全も提供します。NSLayoutAnchor クラスには、型情報と制約を作成するためのサブクラス固有のメソッドを追加する多数くのサブクラスがあります。これにより、無効な制約が誤って作成されるのを防ぐことができます。たとえば、水平アンカー (leadingAnchor または trailingAnchor) は他の水平アンカーでのみ制約できます。同様に、乗数はサイズの制約にのみ指定できます。
これらのルールは NSLayoutConstraint API によって強制されません。代わりに、無効な制約を作成すると、その制約は実行時に例外を throw します。したがって、レイアウトアンカーは、実行時エラーをコンパイル時エラーに変換するのに役立ちます。
詳細については、NSLayoutAnchor クラスリファレンス を参照してください。
NSLayoutConstraint クラス
NSLayoutConstraint クラスの constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: コンビニエンスメソッドを使用して、制約を直接作成することもできます。このメソッドは、制約方程式をコードに明示的に変換します。各パラメータは方程式の一部に対応します (制約方程式 を参照の事)。
レイアウトアンカー API によるアプローチとは異なり、レイアウトに影響を与えない場合であっても、各パラメータの値を指定しなければなりません。最終結果は、かなり読みにくい定型コードになり、通常は解読しにくくなります。たとえば、リスト 13-2 のコードは、リスト 13-1 のコードと機能的には全く同じです。
リスト 13-2 制約を直接インスタンス化する
1 NSLayoutConstraint(item: myView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true 2 3 NSLayoutConstraint(item: myView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailingMargin, multiplier: 1.0, constant: 0.0).isActive = true 4 5 NSLayoutConstraint(item: myView, attribute: .height, relatedBy: .equal, toItem: myView, attribute:.width, multiplier: 2.0, constant:0.0).isActive = true
iOS では、NSLayoutAttribute の列挙型にビューのマージンの値が含まれています。これは、layoutMarginsGuide プロパティを経由せずにマージンに制約を作成できることを意味します。ただし、読み取り可能なコンテンツガイドへの制約に対しては、引き続き readableContentGuide プロパティを使用する必要があります。
レイアウトアンカー API とは異なり、コンビニエンスメソッドは特定の制約の重要な機能を強調表示しません。その結果、コードをスキャンするときに、重要な詳細を見逃しやすくなります。さらに、コンパイラは制約の静的分析を何も実行しません。あなたは無効な制約を自由に作成できます。これらの制約は、実行時に例外を throw します。したがって、iOS 8 または OS X v10.10 以前をサポートする必要がない限り、コードを新しいレイアウトアンカー API に移行することを検討してください。
詳細については、NSLayoutConstraint クラスリファレンス を参照してください。
視覚書式言語
視覚書式言語 (Visual Format Language) では、ASCII アートのような文字列を使用して制約を定義できます。これにより、制約の視覚的な説明表現が提供されます。視覚書式言語には、以下の利点と欠点があります。
- 自動レイアウトは、視覚書式言語を使用してコンソールに制約を出力します。このため、デバッグメッセージは、制約の作成に使用されたコードと非常によく似ています。
- 視覚書式言語では、非常にコンパクトな式を使用して、一度に複数の制約を作成できます。
- 視覚書式言語では、有効な制約のみを作成できます。
- 表記は、完全性よりも優れた視覚化を強調します。したがって、視覚書式言語を使用して作成できない制約 (アスペクト比など) があります。
- コンパイラは文字列を全く検証しません。実行時テストでのみ間違いを発見できます。
リスト 13-1 では、例は視覚書式言語を使用して書き直されています:
リスト 13-3 視覚書式言語による制約の作成
1 let views = ["myView" : myView] 2 let formatString = "|-[myView]-|" 3 4 let constraints = NSLayoutConstraint.constraints(withVisualFormat: formatString, options: .alignAllTop, metrics: nil, views: views) 5 6 NSLayoutConstraint.activate(constraints)
この例では、先端の制約と後端の制約の両方を作成してアクティブにします。デフォルトの間隔を使用する場合、視覚書式言語は常にスーパービューのマージンに 0 ポイントの制約を作成するため、これらの制約は以前の例と同一です。ただし、リスト 13-3 ではアスペクト比の制約を作成できません。
1 行に複数の項目を含む、より複雑なビューを作成する場合、視覚書式言語は垂直方向の整列と水平方向の間隔の両方を指定します。記述したように、この例にはビューが 1 つしかないため (スーパービューは含まない)、"すべてを上端に整列" オプションはレイアウトに影響しません。
視覚書式言語を使用して制約を作成するには:
- View 辞書を作成します。この辞書には、キーと View オブジェクト (またはレイアウトガイドなどの、自動レイアウトで制約されるべきその他の項目) が値として文字列として含まれていなければなりません。キーを使用して、書式文字列の View を識別します。
- (オプション) metrics の辞書を作成します。この辞書には、キーの文字列と値の NSNumber オブジェクトの文字列が絶対に必要です。キーを使用して、書式文字列で定数値を表します。
- 項目の単一の行または列をレイアウトして、書式文字列を作成します。
- NSLayoutConstraint クラスの constraintWithVisualFormat:options:metrics:views: メソッドを呼び出します。このメソッドは、すべての制約を含む配列を返します。
- NSLayoutConstraint クラスの activateConstraints: メソッドを呼び出して、制約をアクティブにします。
Objective-C を使用する場合は、NSDictionaryOfVariableBindings マクロを使用して View の辞書を作成します。Swift では、自分で辞書を作成しなければなりません。
詳細については、付録 視覚書式言語 を参照してください。
前:デバッグの秘訣とヒント 次:サイズクラス固有のレイアウト