iOS6 Auto Layout

   2012/12/10
クラスメソッド かけがわ
自己紹介
アジェンダ
• Auto Layout
  •   Auto Layoutの基礎知識
  •   Interface BuilderでAuto Layoutを設定
  •   ソースコードでAuto Layoutを設定
  •   Auto Layout 補足
Auto Layoutの基礎知識
Auto Layout
• 「制約」ベースのレイアウトシステム

• Autosizingを置き換えるもの

• Macアプリケーションでは、OS X Lionで既
  に導入されている
Constraint
• レイアウトを決定するための「制約」

• 他のUIコンポーネントとの相対的な位置・
  サイズを定義

• 制約はNSLayoutConstraintクラスのインス
  タンスによって表現される
Auto LayoutとAutosizingの違い
           Autosizing
• サブビューの親ビューに対する相対関係
  を指定する
 • 親ビューとの間のマージン
 • 親ビューに追従してリサイズするか
Auto LayoutとAutosizingの違い
          Auto Layout
• レイアウト上のルールを制約として定義
 • サブビューの親ビューに対する相対位置
 • 兄弟ビューとの相対位置やサイズ
 • 自身のサイズ

• ルールは必ずしも厳密に満たされない
 • サイズや位置に関して、「20px以上」や
   「10px以下」といった表現が可能
 • 優先順位
Leading & Trailing
• アラビア語など、右側が文頭になる環境に対する、レイアウ
  ト上のローカライズを容易にするための機能

• Leadingは文字列の先頭側、Trailingは文字列の末尾側を指す

• 日本語や英語の環境では、LeadingはLeft、TrailingはRightに対
  応する

• アラビア語など、右側が文頭になる環境では、LeadingがRight、
  TrailingがLeftに対応する

• LeftやRightの代わりにLeadingやTrailingを利用しておくと、OS
  の言語がアラビア語に設定されている環境ではレイアウトの
  位置が左右反転する
Leading & Trailing
親ビュー内でのボタンの水平方向のアライメントに関して、Leading側に寄せて
20pxのスペースを置くという制約を追加した場合




                     OSの言語設定がアラビア
  OSの言語設定が英語
                           語
Auto Layoutの使い方
使い方
使い方は2通り

• Interface Builder上で制約を設定する
• ソースコードでNSLayoutConstraintクラス
  を使って設定する
Interface Builderで制約を設定す
                る
Auto Layoutの切り替え
• ファイルインスペクタのUse
  Autolayoutを有効にする

• Use Autolayoutを無効にすれば従
  来通り

• iOS5.x以前でUse Autolayoutを有効
  にするとクラッシュするので注意
Interface Builder上のメニュー
Interface Builder上のメニュー
Interface Builder上のメニュー


             コンポーネントのアライ
             メントに関する制約を追
             加する操作
Interface Builder上のメニュー


             コンポーネントの相対的
             な位置やサイズを固定す
             る制約を追加する操作
Interface Builder上のメニュー



Interface Builder上でコンポーネントをリサイズした場合に
、周辺コンポーネントに既存の制約を適用して移動やリサ
イズなどを行うかを設定する

• Siblings and Ancestors
   親と兄弟に制約を適用する
• Descendants
   子に制約を適用する
Align – 端揃え
• Left Edges
   •   複数のコンポーネントの左端の水平位置を揃える制約を追加する
   •   追加される制約はDirectionの設定による

• Right Edges
   •   複数のコンポーネントの右端の水平位置を揃える制約を追加する
   •   追加される制約はDirectionの設定による

• Top Edges
   •   複数のコンポーネントの上端の垂直位置を揃える制約を追加する
   •   追加される制約はTop Alignment

• Bottom Edges
   •   複数のコンポーネントの下端の垂直位置を揃える制約を追加する
   •   追加される制約はBottom Alignment
Align – 基準位置揃え
• Horizontal Centers
   •   複数のコンポーネントの水平方向の中心位置を揃える制約を追
       加する
   •   追加される制約はCenter X Alignment

• Vertical Centers
   •   複数のコンポーネントの垂直方向の中心位置を揃える制約を追
       加する
   •   追加される制約はCenter Y Alignment

• Baselines
   •   複数のコンポーネントのベースライン位置関係を固定する制約
       を追加する
   •   追加される制約はBaseline Alignment
Align – 親ビュー内でセンタリン
           グ
• Horizontal Center in Container
   • コンポーネントとその親コンテナの水平方向の中心位置
       を揃える制約を追加する
   • 追加される制約はCenter X Alignment

• Vertical Center in Container
   • コンポーネントとその親コンテナの垂直方向の中心位置
       を揃える制約を追加する
   • 追加される制約はCenter Y Alignment
Pin – サイズ
• Width
   •   コンポーネントの幅に関する制約を追加する
   •   追加される制約はWidth
   •   制約は対象コンポーネントに追加

• Height
   •   コンポーネントの高さに関する制約を追加する
   •   追加される制約はHeight
   •   制約は対象コンポーネントに追加
Pin – コンポーネント間の間隔
• Horizontal Spacing
   •   2つのコンポーネントの間の水平方向の距離に関す
       る制約を追加する
   •   追加される制約はHorizontal Space

• Vertical Spacing
   •   2つのコンポーネントの間の垂直方向の距離に関す
       る制約を追加する
   •   追加される制約はVertical Space
Pin – 親ビューの端との間隔
•   Leading Space to SuperView
     •    コンポーネントの左端とその親ビューの左端の距離に関する制約を追加する
     •    追加される制約はHorizontal Space

•   Trailing Space to SuperView
     •    コンポーネントの右端とその親ビューの右端の距離に関する制約を追加する
     •    追加される制約はHorizontal Space

•   Top Space to SuperView
     •    コンポーネントの上端とその親ビューの上端の距離に関する制約を追加する
     •    追加される制約はVertical Space

•   Bottom Space to SuperView
     •    コンポーネントの下端とその親ビューの下端の距離に関する制約を追加する
     •    追加される制約はVertical Space
Pin – サイズの連動
• Widths Equally
  • 複数のコンポーネントの幅を等しくする制約を追加する
  • 追加される制約はEqual Widths

• Heights Equally
   •   複数のコンポーネントの高さを等しくする制約を追加す
       る
   •   追加される制約はEqual Heights
Demo
制約の種類
• アライメントに関する制約(7種類)
 Leading(Left or Right) Alignment, Trailing(Right or Left) Alignment, Center X
 Alignment
 Top Alignment, Bottom Alignment, Center Y Alignment, Baseline Alignment

• 相対位置に関する制約(2種類)
 Horizontal Space
 Vertical Space

• サイズに関する制約(2種類)
 Width, Height

• サイズの連動に関する制約(2種類)
 Equal Widths, Equal Heights
制約の種類
• アライメントに関する制約(7種類)
 Leading(Left or Right) Alignment, Trailing(Right or Left) Alignment, Center X
 Alignment
 Top Alignment, Bottom Alignment, Center Y Alignment, Baseline Alignment

• 相対位置に関する制約(2種類)
 Horizontal Space
 Vertical Space

• サイズに関する制約(2種類)
 Width, Height

• サイズの連動に関する制約(2種類)実際に追加される制約は
 Equal Widths, Equal Heights                              13種類
制約の種類
• アライメントに関する制約(7種類)
 Leading(Left or Right) Alignment, Trailing(Right or Left) Alignment, Center X
 Alignment
 Top Alignment, Bottom Alignment, Center Y Alignment, Baseline Alignment

• 相対位置に関する制約(2種類)
 Horizontal Space
 Vertical Space

• サイズに関する制約(2種類)
 Width, Height

• サイズの連動に関する制約(2種類)実際に追加される制約は
 Equal Widths, Equal Heights                    大きく分類すると4種類
                                                   13種類
制約の種類
• Interface Builder上から実行できる制約追加のコマ
  ンドは19種類

• でも実際には、制約の種類と制約の適用対象のバ
  リエーションの組み合わせでInterface Builderのコ
  マンドの種類が多くなっているだけ

• 制約の適用対象のバリエーション
 •   親ビューとその子コンポーネント
 •   兄弟コンポーネント同士
 •   対象コンポーネントのみ
User Constraint
• Interface Builder上で設定される制約
  には2種類あり、アイコンの色が異
  なっている

• 青いアイコンはユーザー編集可能な
  制約を表す(User Constraint)
  キャンバス上の制約インジケーターが太
  い

• 紫のアイコンはInterface Builderが自
  動的に挿入した制約
  キャンバス上の制約インジケーターが細
  い
User Constraint
• User Constraintはシーンやキャンバス、サ
  イズインスペクタから削除することがで
  きる

• Interface Builderが追加した制約は、サイズ
  インスペクタのConstraintsで対象の制約を
  選び、Promote to User Constraintを選択す
  るとUser Constraintにすることができる
IBでAuto Layoutを利用すると
  よくわからない動きをする・・・
• Auto Layoutは実行時にレイアウトを決定す
  るのに十分な制約を設定する必要がある

• 必要となる制約が不足している場合、
  Interface Builderが制約を自動で設定する
 • このため、制約を編集すると既存の制約が壊
   されるように感じる
IBでAuto Layoutを利用する際のポイン
               ト
• 自動設定された制約(紫アイコン)と
  ユーザー設定の制約(青アイコン)を意
  識すると思い通りに設定できる

• 実体であるNSLayoutConstraintを意識する
NSLayoutConstraintで制約を設定す
               る
NSLayoutConstraint
• レイアウトの制約を表すクラス

• 基本的にイミュータブルなので、制約を
  変更する際は新しいインスタンスを作成
  して差し替える
NSLayoutConstraintの計算式
属性値1 == 属性値2 * 乗数 + 定数
NSLayoutConstraint
• id firstItem
    •   属性値の計算結果を反映するオブジェクト

• NSLayoutAttribute firstAttribute
    •   計算結果を反映する属性
    •   firstItemで指定されたオブジェクトに対して、この属性に対応する値
        を属性値として反映する

• id secondItem
    •   計算式に利用する属性値を取得するオブジェクト

• NSLayoutAttribute secondAttribute
    •   計算式に利用する属性
    •   属性値の取得元はsecondItemで指定されたオブジェクト
NSLayoutConstraint
• id firstItem
    •   属性値の計算結果を反映するオブジェクト

• NSLayoutAttribute firstAttribute
    •   計算結果を反映する属性
    •   firstItemで指定されたオブジェクトに対して、この属性に対応する値
        を属性値として反映する

• id secondItem
    •   計算式に利用する属性値を取得するオブジェクト

• NSLayoutAttribute secondAttribute
    •   計算式に利用する属性
    •   属性値の取得元はsecondItemで指定されたオブジェクト

                      firstItemは計算結果を反映する側
                   secondItemは計算式に値を利用する側
NSLayoutConstraint
• CGFloat constant
    •   計算式の中で属性値の算出に利用する定数値
    •   この値だけは、例外的にNSLayoutConstraintのインスタンス化後に変更
        できる

• CGFloat multiplier
    •   計算式の中で属性値の算出に利用する乗算値
    •   属性値同士の比率を定義するのに使用する
    •   今のところ乗算値を利用した制約の定義はInterface Builderでサポート
        されていない

• NSLayoutPriority priority
    •   制約の優先順位

• NSLayoutRelation relation
    •   計算式とその計算結果の関係性を指定する
NSLayoutAttribute
• 制約の対象となる属性を表す列挙型

• ボタン1の「下端」から10px下側に、ボ
  タン2の「上端」がくるよう配置する制
  約の場合
 • ボタン1の属性はNSLayoutAttributeBottom
 • ボタン2の属性はNSLayoutAttributeTop
NSLayoutAttribute
typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
   NSLayoutAttributeLeft = 1,
   NSLayoutAttributeRight,
   NSLayoutAttributeTop,
   NSLayoutAttributeBottom,
   NSLayoutAttributeLeading,
   NSLayoutAttributeTrailing,
   NSLayoutAttributeWidth,
   NSLayoutAttributeHeight,
   NSLayoutAttributeCenterX,
   NSLayoutAttributeCenterY,
   NSLayoutAttributeBaseline,

     NSLayoutAttributeNotAnAttribute = 0
};
NSLayoutRelation
• 計算式とその計算結果の関係性を表す列
  挙型

• 「等しい」「以上」「以下」の3つ

typedef NS_ENUM(NSInteger, NSLayoutRelation) {
   NSLayoutRelationLessThanOrEqual = -1,
   NSLayoutRelationEqual = 0,
   NSLayoutRelationGreaterThanOrEqual = 1,
};
NSLayoutPriority
• 競合する制約間の優先順位を表す値

• この値が高い制約から優先的に制約で定義された条件が満たされて
  いく

• 1から1000までのCGFloat値

• いくつかの定数値がUILayoutPriority列挙型として用意されているの
  で、基本的にこの値を利用するのがよさそう

enum {
   UILayoutPriorityRequired = 1000,
   UILayoutPriorityDefaultHigh = 750,
   UILayoutPriorityDefaultLow = 250,
   UILayoutPriorityFittingSizeLevel = 50
};
typedef float UILayoutPriority;
NSLayoutConstraintの計算式
属性値1 == 属性値2 * 乗数 + 定数
NSLayoutConstraintの計算式
属性値1 == 属性値2 * 乗数 + 定数

                                constant

                          multiplier
            relation


    firstItem            secondItem
 firstAttribute        secondAttribute
NSLayoutConstraintの計算式
• ボタン1の右端から右に10pxの位置にボタン2の左端
  が位置する場合

 button2.left == button1.right * 1 + 10
• ビュー2の幅がビュー1の幅の3倍の場合

   view2.width == view1.width * 3 + 0
NSLayoutConstraintの計算式
• ボタン1の右端から右に10pxの位置にボタン2の左端
  が位置する場合

 button2.left == button1.right * 1 + 10
• ビュー2の幅がビュー1の幅の3倍の場合

   view2.width == view1.width * 3 + 0


    すべての制約は計算式で表現される
NSLayoutConstraintの作成
 • Visual Format Languageを利用する方法
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view1]-|"
                       options:0
                       metrics:nil
                         views:views];



 • Visual Format Languageを利用しない方法
[NSLayoutConstraint constraintWithItem:view1
                attribute:NSLayoutAttributeHeight
                relatedBy:NSLayoutRelationEqual
                  toItem:view2
                attribute:NSLayoutAttributeHeight
                multiplier:2.0f
                 constant:0.0f];
Visual Format Language
• 制約をNSStringで表現するDSLのような
  もの

      @"V:|-[view1]-20-[view2]-|”
Visual Format Language
• 制約をNSStringで表現するDSLのような
  もの

           @"V:|-[view1]-20-[view2]-|”
  "V:"                                     “[view2]"
垂直方向の                                    コンポーネント
レイアウト                                    のインスタンス

                                  "-20-"
    "|"                       20pxのスペース
  親ビューの            "-"
   エッジ            スペース
                 (デフォルト
                   値)
Visual Format Language
• 制約をNSStringで表現するDSLのような
  もの

         @"V:|-[view1]-20-[view2]-|”
       以下の3つの制約を表現している
・垂直方向において、view1の上端は親ビューの上端からデフォルト値(20px)下
にある
・垂直方向において、view1の下端とview2の上端は20px離れている
・垂直方向において、view2の下端は親ビューの下端からデフォルト値(20px)上
にある
Visual Format Language
• 文字列なのでコンパイラによるチェックは
  ない

• 実行時にパースできないとエラーが発生す
  る

• 詳細はAppleの公式ドキュメントを参照

                           Visual Format Language
https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/Autolayou
                              tPG/Articles/formatLanguage.html
Demo
コード
NSDictionary *views = NSDictionaryOfVariableBindings(view1, view2);

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view1]-|"
                                       options:0
                                       metrics:nil
                                        views:views]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view1]-20-[view2]-|"
                                       options:NSLayoutFormatAlignAllCenterX
                                       metrics:nil
                                        views:views]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view1(==view2)]"
                                       options:0
                                       metrics:nil
                                        views:views]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:view1
                                attribute:NSLayoutAttributeHeight
                                relatedBy:NSLayoutRelationEqual
                                  toItem:view2
                                attribute:NSLayoutAttributeHeight
                                multiplier:2.0f
                                 constant:0.0f]];
Auto Layout 補足
Intrinsic Content Size
• 一部のUIコンポーネントは自身の推奨サイズを、UIViewで定
  義されたintrinsicConstentSizeメソッドから取得できる

• UIButton, UILabelなどが推奨サイズを持っている

• ラベルのみのUIButtonであれば、内部のテキストの幅・高さ
  にパディングを加えたものが推奨サイズとなる

• 内部のコンテンツの大きさが変化すると、推奨サイズも変化
  する

• Auto Layoutにおいては、幅や高さを決定する制約が不足して
  いる場合に推奨サイズが使用される
推奨サイズを持たない場合
Vertical Space (148)



Center X Alignment



Horizontal Space (36)



Vertical Space (149)
推奨サイズを持つ場合
Vertical Space (148)



Center X Alignment
推奨サイズを持つ場合
Vertical Space (148)



Center X Alignment


ボタンの幅と高さは推
奨サイズが採用される
ので、制約を追加する
必要なし
推奨サイズの優先順位
• まわりのコンポーネントの制約によって
  は、推奨サイズを実現できないときがあ
  る

• 制約同士が競合した場合と同じように、
  推奨サイズも優先順位がつけられて実際
  のレイアウトに適用される
 • Content Hugging Priority
 • Content Compression Resistance Priority
Content Hugging Priority
• UIコンポーネントのサイズが制約によって推奨サ
  イズより大きくなる場合の「大きくなりにくさ」
  を決定する

• 実際にはNSLayoutPriorityの値で制約間での優先順
  位を設定している

• デフォルト値はUILayoutPriorityDefaultLow

• UIViewにメソッドが用意されている
  – contentHuggingPriorityForAxis:
  – setContentHuggingPriority:forAxis:
Content Compression Resistance Priority
• UIコンポーネントのサイズが制約によって推奨サ
  イズより小さくなる場合の「小さくなりにくさ」
  を決定する

• Content Hugging Priority同様、実際には優先順位の
  値が設定される

• デフォルト値はUILayoutPriorityDefaultHigh

• UIViewにメソッドが用意されている
  – contentCompressionResistancePriorityForAxis:
  – setContentCompressionResistancePriority:forAxis:
動的なレイアウトへの対応
• ビューのプロパティが変更された場合な
  どに、動的にレイアウトを変更したい

• 今まではlayoutSubviewsをオーバーライド
  してレイアウト処理を書いていた

• 制約を利用する場合も、同じようにUIView
  に制約変更用のライフサイクルメソッド
  が用意されている
動的なレイアウトへの対応
- updateConstraints
   •   オーバーライドして制約の更新処理を記述する
   •   layoutSubviewsと同じく、システムによって呼ばれるので
       自分で呼び出さない
   •   このメソッドをオーバーライドする場合は、
       layoutSubviewsによるレイアウト処理はオーバーライドし
       ないこと
   •   逆にlayoutSubviewsをオーバーライドする場合は、
       updateConstraintはオーバーライドしない

- setNeedsUpdateConstraints
   •   updateConstraintsの実行をトリガする
   •   layoutSubviewsに対するsetNeedsLayoutと同じ
Auto Layoutのデバッグ
UIViewのUIConstraintBasedLayoutDebuggingカテゴリに定義されているデバッグ
用のメソッドを利用する

•   - (NSArray *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis
     縦軸・横軸のそれぞれについて、現在適用されている制約を返す
     UILayoutConstraintAxisで制約を取得したい軸を指定する

•   - (BOOL)hasAmbiguousLayout
     制約が不足してレイアウトが決定できない箇所がある場合YESを返す

•   - (void)exerciseAmbiguityInLayout
     hasAmbiguousLayoutがYESの場合、可能性のあるレイアウトをランダムで画面に適用する




リリースビルド作成の際は必ずこれらのメソッドは外すこ
            と!
Demo
Auto Layoutのメリット
• より柔軟なレイアウトをframeを操作せず
  に実現できる

• 込み入ったレイアウトを宣言的にプログ
  ラミングすることができる

• Visual Format Languageによる定義が手軽
Auto Layoutのデメリット
• 学習コストが低いとは言えない

• シンプルなレイアウトを組むの場合は
  AutoResizingMaskを使う方が手軽

• iOS5では使えない
ご清聴ありがとうございました

iOS6 Auto Layout

  • 1.
    iOS6 Auto Layout 2012/12/10 クラスメソッド かけがわ
  • 2.
  • 3.
    アジェンダ • Auto Layout • Auto Layoutの基礎知識 • Interface BuilderでAuto Layoutを設定 • ソースコードでAuto Layoutを設定 • Auto Layout 補足
  • 4.
  • 5.
    Auto Layout • 「制約」ベースのレイアウトシステム •Autosizingを置き換えるもの • Macアプリケーションでは、OS X Lionで既 に導入されている
  • 6.
    Constraint • レイアウトを決定するための「制約」 • 他のUIコンポーネントとの相対的な位置・ サイズを定義 • 制約はNSLayoutConstraintクラスのインス タンスによって表現される
  • 7.
    Auto LayoutとAutosizingの違い Autosizing • サブビューの親ビューに対する相対関係 を指定する • 親ビューとの間のマージン • 親ビューに追従してリサイズするか
  • 8.
    Auto LayoutとAutosizingの違い Auto Layout • レイアウト上のルールを制約として定義 • サブビューの親ビューに対する相対位置 • 兄弟ビューとの相対位置やサイズ • 自身のサイズ • ルールは必ずしも厳密に満たされない • サイズや位置に関して、「20px以上」や 「10px以下」といった表現が可能 • 優先順位
  • 9.
    Leading & Trailing •アラビア語など、右側が文頭になる環境に対する、レイアウ ト上のローカライズを容易にするための機能 • Leadingは文字列の先頭側、Trailingは文字列の末尾側を指す • 日本語や英語の環境では、LeadingはLeft、TrailingはRightに対 応する • アラビア語など、右側が文頭になる環境では、LeadingがRight、 TrailingがLeftに対応する • LeftやRightの代わりにLeadingやTrailingを利用しておくと、OS の言語がアラビア語に設定されている環境ではレイアウトの 位置が左右反転する
  • 10.
  • 11.
  • 12.
    使い方 使い方は2通り • Interface Builder上で制約を設定する •ソースコードでNSLayoutConstraintクラス を使って設定する
  • 13.
  • 14.
    Auto Layoutの切り替え • ファイルインスペクタのUse Autolayoutを有効にする • Use Autolayoutを無効にすれば従 来通り • iOS5.x以前でUse Autolayoutを有効 にするとクラッシュするので注意
  • 15.
  • 16.
  • 17.
    Interface Builder上のメニュー コンポーネントのアライ メントに関する制約を追 加する操作
  • 18.
    Interface Builder上のメニュー コンポーネントの相対的 な位置やサイズを固定す る制約を追加する操作
  • 19.
  • 20.
    Align – 端揃え •Left Edges • 複数のコンポーネントの左端の水平位置を揃える制約を追加する • 追加される制約はDirectionの設定による • Right Edges • 複数のコンポーネントの右端の水平位置を揃える制約を追加する • 追加される制約はDirectionの設定による • Top Edges • 複数のコンポーネントの上端の垂直位置を揃える制約を追加する • 追加される制約はTop Alignment • Bottom Edges • 複数のコンポーネントの下端の垂直位置を揃える制約を追加する • 追加される制約はBottom Alignment
  • 21.
    Align – 基準位置揃え •Horizontal Centers • 複数のコンポーネントの水平方向の中心位置を揃える制約を追 加する • 追加される制約はCenter X Alignment • Vertical Centers • 複数のコンポーネントの垂直方向の中心位置を揃える制約を追 加する • 追加される制約はCenter Y Alignment • Baselines • 複数のコンポーネントのベースライン位置関係を固定する制約 を追加する • 追加される制約はBaseline Alignment
  • 22.
    Align – 親ビュー内でセンタリン グ • Horizontal Center in Container • コンポーネントとその親コンテナの水平方向の中心位置 を揃える制約を追加する • 追加される制約はCenter X Alignment • Vertical Center in Container • コンポーネントとその親コンテナの垂直方向の中心位置 を揃える制約を追加する • 追加される制約はCenter Y Alignment
  • 23.
    Pin – サイズ •Width • コンポーネントの幅に関する制約を追加する • 追加される制約はWidth • 制約は対象コンポーネントに追加 • Height • コンポーネントの高さに関する制約を追加する • 追加される制約はHeight • 制約は対象コンポーネントに追加
  • 24.
    Pin – コンポーネント間の間隔 •Horizontal Spacing • 2つのコンポーネントの間の水平方向の距離に関す る制約を追加する • 追加される制約はHorizontal Space • Vertical Spacing • 2つのコンポーネントの間の垂直方向の距離に関す る制約を追加する • 追加される制約はVertical Space
  • 25.
    Pin – 親ビューの端との間隔 • Leading Space to SuperView • コンポーネントの左端とその親ビューの左端の距離に関する制約を追加する • 追加される制約はHorizontal Space • Trailing Space to SuperView • コンポーネントの右端とその親ビューの右端の距離に関する制約を追加する • 追加される制約はHorizontal Space • Top Space to SuperView • コンポーネントの上端とその親ビューの上端の距離に関する制約を追加する • 追加される制約はVertical Space • Bottom Space to SuperView • コンポーネントの下端とその親ビューの下端の距離に関する制約を追加する • 追加される制約はVertical Space
  • 26.
    Pin – サイズの連動 •Widths Equally • 複数のコンポーネントの幅を等しくする制約を追加する • 追加される制約はEqual Widths • Heights Equally • 複数のコンポーネントの高さを等しくする制約を追加す る • 追加される制約はEqual Heights
  • 27.
  • 28.
    制約の種類 • アライメントに関する制約(7種類) Leading(Leftor Right) Alignment, Trailing(Right or Left) Alignment, Center X Alignment Top Alignment, Bottom Alignment, Center Y Alignment, Baseline Alignment • 相対位置に関する制約(2種類) Horizontal Space Vertical Space • サイズに関する制約(2種類) Width, Height • サイズの連動に関する制約(2種類) Equal Widths, Equal Heights
  • 29.
    制約の種類 • アライメントに関する制約(7種類) Leading(Leftor Right) Alignment, Trailing(Right or Left) Alignment, Center X Alignment Top Alignment, Bottom Alignment, Center Y Alignment, Baseline Alignment • 相対位置に関する制約(2種類) Horizontal Space Vertical Space • サイズに関する制約(2種類) Width, Height • サイズの連動に関する制約(2種類)実際に追加される制約は Equal Widths, Equal Heights 13種類
  • 30.
    制約の種類 • アライメントに関する制約(7種類) Leading(Leftor Right) Alignment, Trailing(Right or Left) Alignment, Center X Alignment Top Alignment, Bottom Alignment, Center Y Alignment, Baseline Alignment • 相対位置に関する制約(2種類) Horizontal Space Vertical Space • サイズに関する制約(2種類) Width, Height • サイズの連動に関する制約(2種類)実際に追加される制約は Equal Widths, Equal Heights 大きく分類すると4種類 13種類
  • 31.
    制約の種類 • Interface Builder上から実行できる制約追加のコマ ンドは19種類 • でも実際には、制約の種類と制約の適用対象のバ リエーションの組み合わせでInterface Builderのコ マンドの種類が多くなっているだけ • 制約の適用対象のバリエーション • 親ビューとその子コンポーネント • 兄弟コンポーネント同士 • 対象コンポーネントのみ
  • 32.
    User Constraint • InterfaceBuilder上で設定される制約 には2種類あり、アイコンの色が異 なっている • 青いアイコンはユーザー編集可能な 制約を表す(User Constraint) キャンバス上の制約インジケーターが太 い • 紫のアイコンはInterface Builderが自 動的に挿入した制約 キャンバス上の制約インジケーターが細 い
  • 33.
    User Constraint • UserConstraintはシーンやキャンバス、サ イズインスペクタから削除することがで きる • Interface Builderが追加した制約は、サイズ インスペクタのConstraintsで対象の制約を 選び、Promote to User Constraintを選択す るとUser Constraintにすることができる
  • 34.
    IBでAuto Layoutを利用すると よくわからない動きをする・・・ • Auto Layoutは実行時にレイアウトを決定す るのに十分な制約を設定する必要がある • 必要となる制約が不足している場合、 Interface Builderが制約を自動で設定する • このため、制約を編集すると既存の制約が壊 されるように感じる
  • 35.
    IBでAuto Layoutを利用する際のポイン ト • 自動設定された制約(紫アイコン)と ユーザー設定の制約(青アイコン)を意 識すると思い通りに設定できる • 実体であるNSLayoutConstraintを意識する
  • 36.
  • 37.
  • 38.
  • 39.
    NSLayoutConstraint • id firstItem • 属性値の計算結果を反映するオブジェクト • NSLayoutAttribute firstAttribute • 計算結果を反映する属性 • firstItemで指定されたオブジェクトに対して、この属性に対応する値 を属性値として反映する • id secondItem • 計算式に利用する属性値を取得するオブジェクト • NSLayoutAttribute secondAttribute • 計算式に利用する属性 • 属性値の取得元はsecondItemで指定されたオブジェクト
  • 40.
    NSLayoutConstraint • id firstItem • 属性値の計算結果を反映するオブジェクト • NSLayoutAttribute firstAttribute • 計算結果を反映する属性 • firstItemで指定されたオブジェクトに対して、この属性に対応する値 を属性値として反映する • id secondItem • 計算式に利用する属性値を取得するオブジェクト • NSLayoutAttribute secondAttribute • 計算式に利用する属性 • 属性値の取得元はsecondItemで指定されたオブジェクト firstItemは計算結果を反映する側 secondItemは計算式に値を利用する側
  • 41.
    NSLayoutConstraint • CGFloat constant • 計算式の中で属性値の算出に利用する定数値 • この値だけは、例外的にNSLayoutConstraintのインスタンス化後に変更 できる • CGFloat multiplier • 計算式の中で属性値の算出に利用する乗算値 • 属性値同士の比率を定義するのに使用する • 今のところ乗算値を利用した制約の定義はInterface Builderでサポート されていない • NSLayoutPriority priority • 制約の優先順位 • NSLayoutRelation relation • 計算式とその計算結果の関係性を指定する
  • 42.
    NSLayoutAttribute • 制約の対象となる属性を表す列挙型 • ボタン1の「下端」から10px下側に、ボ タン2の「上端」がくるよう配置する制 約の場合 • ボタン1の属性はNSLayoutAttributeBottom • ボタン2の属性はNSLayoutAttributeTop
  • 43.
    NSLayoutAttribute typedef NS_ENUM(NSInteger, NSLayoutAttribute){ NSLayoutAttributeLeft = 1, NSLayoutAttributeRight, NSLayoutAttributeTop, NSLayoutAttributeBottom, NSLayoutAttributeLeading, NSLayoutAttributeTrailing, NSLayoutAttributeWidth, NSLayoutAttributeHeight, NSLayoutAttributeCenterX, NSLayoutAttributeCenterY, NSLayoutAttributeBaseline, NSLayoutAttributeNotAnAttribute = 0 };
  • 44.
    NSLayoutRelation • 計算式とその計算結果の関係性を表す列 挙型 • 「等しい」「以上」「以下」の3つ typedef NS_ENUM(NSInteger, NSLayoutRelation) { NSLayoutRelationLessThanOrEqual = -1, NSLayoutRelationEqual = 0, NSLayoutRelationGreaterThanOrEqual = 1, };
  • 45.
    NSLayoutPriority • 競合する制約間の優先順位を表す値 • この値が高い制約から優先的に制約で定義された条件が満たされて いく • 1から1000までのCGFloat値 • いくつかの定数値がUILayoutPriority列挙型として用意されているの で、基本的にこの値を利用するのがよさそう enum { UILayoutPriorityRequired = 1000, UILayoutPriorityDefaultHigh = 750, UILayoutPriorityDefaultLow = 250, UILayoutPriorityFittingSizeLevel = 50 }; typedef float UILayoutPriority;
  • 46.
  • 47.
    NSLayoutConstraintの計算式 属性値1 == 属性値2* 乗数 + 定数 constant multiplier relation firstItem secondItem firstAttribute secondAttribute
  • 48.
    NSLayoutConstraintの計算式 • ボタン1の右端から右に10pxの位置にボタン2の左端 が位置する場合 button2.left == button1.right * 1 + 10 • ビュー2の幅がビュー1の幅の3倍の場合 view2.width == view1.width * 3 + 0
  • 49.
    NSLayoutConstraintの計算式 • ボタン1の右端から右に10pxの位置にボタン2の左端 が位置する場合 button2.left == button1.right * 1 + 10 • ビュー2の幅がビュー1の幅の3倍の場合 view2.width == view1.width * 3 + 0 すべての制約は計算式で表現される
  • 50.
    NSLayoutConstraintの作成 • VisualFormat Languageを利用する方法 [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view1]-|" options:0 metrics:nil views:views]; • Visual Format Languageを利用しない方法 [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeHeight multiplier:2.0f constant:0.0f];
  • 51.
    Visual Format Language •制約をNSStringで表現するDSLのような もの @"V:|-[view1]-20-[view2]-|”
  • 52.
    Visual Format Language •制約をNSStringで表現するDSLのような もの @"V:|-[view1]-20-[view2]-|” "V:" “[view2]" 垂直方向の コンポーネント レイアウト のインスタンス "-20-" "|" 20pxのスペース 親ビューの "-" エッジ スペース (デフォルト 値)
  • 53.
    Visual Format Language •制約をNSStringで表現するDSLのような もの @"V:|-[view1]-20-[view2]-|” 以下の3つの制約を表現している ・垂直方向において、view1の上端は親ビューの上端からデフォルト値(20px)下 にある ・垂直方向において、view1の下端とview2の上端は20px離れている ・垂直方向において、view2の下端は親ビューの下端からデフォルト値(20px)上 にある
  • 54.
    Visual Format Language •文字列なのでコンパイラによるチェックは ない • 実行時にパースできないとエラーが発生す る • 詳細はAppleの公式ドキュメントを参照 Visual Format Language https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/Autolayou tPG/Articles/formatLanguage.html
  • 55.
  • 56.
    コード NSDictionary *views =NSDictionaryOfVariableBindings(view1, view2); [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view1]-|" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view1]-20-[view2]-|" options:NSLayoutFormatAlignAllCenterX metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view1(==view2)]" options:0 metrics:nil views:views]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeHeight multiplier:2.0f constant:0.0f]];
  • 57.
  • 58.
    Intrinsic Content Size •一部のUIコンポーネントは自身の推奨サイズを、UIViewで定 義されたintrinsicConstentSizeメソッドから取得できる • UIButton, UILabelなどが推奨サイズを持っている • ラベルのみのUIButtonであれば、内部のテキストの幅・高さ にパディングを加えたものが推奨サイズとなる • 内部のコンテンツの大きさが変化すると、推奨サイズも変化 する • Auto Layoutにおいては、幅や高さを決定する制約が不足して いる場合に推奨サイズが使用される
  • 59.
    推奨サイズを持たない場合 Vertical Space (148) CenterX Alignment Horizontal Space (36) Vertical Space (149)
  • 60.
  • 61.
    推奨サイズを持つ場合 Vertical Space (148) CenterX Alignment ボタンの幅と高さは推 奨サイズが採用される ので、制約を追加する 必要なし
  • 62.
    推奨サイズの優先順位 • まわりのコンポーネントの制約によって は、推奨サイズを実現できないときがあ る • 制約同士が競合した場合と同じように、 推奨サイズも優先順位がつけられて実際 のレイアウトに適用される • Content Hugging Priority • Content Compression Resistance Priority
  • 63.
    Content Hugging Priority •UIコンポーネントのサイズが制約によって推奨サ イズより大きくなる場合の「大きくなりにくさ」 を決定する • 実際にはNSLayoutPriorityの値で制約間での優先順 位を設定している • デフォルト値はUILayoutPriorityDefaultLow • UIViewにメソッドが用意されている – contentHuggingPriorityForAxis: – setContentHuggingPriority:forAxis:
  • 64.
    Content Compression ResistancePriority • UIコンポーネントのサイズが制約によって推奨サ イズより小さくなる場合の「小さくなりにくさ」 を決定する • Content Hugging Priority同様、実際には優先順位の 値が設定される • デフォルト値はUILayoutPriorityDefaultHigh • UIViewにメソッドが用意されている – contentCompressionResistancePriorityForAxis: – setContentCompressionResistancePriority:forAxis:
  • 65.
    動的なレイアウトへの対応 • ビューのプロパティが変更された場合な どに、動的にレイアウトを変更したい • 今まではlayoutSubviewsをオーバーライド してレイアウト処理を書いていた • 制約を利用する場合も、同じようにUIView に制約変更用のライフサイクルメソッド が用意されている
  • 66.
    動的なレイアウトへの対応 - updateConstraints • オーバーライドして制約の更新処理を記述する • layoutSubviewsと同じく、システムによって呼ばれるので 自分で呼び出さない • このメソッドをオーバーライドする場合は、 layoutSubviewsによるレイアウト処理はオーバーライドし ないこと • 逆にlayoutSubviewsをオーバーライドする場合は、 updateConstraintはオーバーライドしない - setNeedsUpdateConstraints • updateConstraintsの実行をトリガする • layoutSubviewsに対するsetNeedsLayoutと同じ
  • 67.
    Auto Layoutのデバッグ UIViewのUIConstraintBasedLayoutDebuggingカテゴリに定義されているデバッグ 用のメソッドを利用する • - (NSArray *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis 縦軸・横軸のそれぞれについて、現在適用されている制約を返す UILayoutConstraintAxisで制約を取得したい軸を指定する • - (BOOL)hasAmbiguousLayout 制約が不足してレイアウトが決定できない箇所がある場合YESを返す • - (void)exerciseAmbiguityInLayout hasAmbiguousLayoutがYESの場合、可能性のあるレイアウトをランダムで画面に適用する リリースビルド作成の際は必ずこれらのメソッドは外すこ と!
  • 68.
  • 69.
    Auto Layoutのメリット • より柔軟なレイアウトをframeを操作せず に実現できる • 込み入ったレイアウトを宣言的にプログ ラミングすることができる • Visual Format Languageによる定義が手軽
  • 70.
    Auto Layoutのデメリット • 学習コストが低いとは言えない •シンプルなレイアウトを組むの場合は AutoResizingMaskを使う方が手軽 • iOS5では使えない
  • 71.