LoginSignup
23
19

More than 5 years have passed since last update.

Autolayout tips for iOS

Last updated at Posted at 2017-07-23

曖昧な制約の確認・テスト

Autolayoutの制約が不十分な場合、hasAmbiguousLayoutを使用することで確認することができます。曖昧な制約が設定されてる場合は、trueが返ります(制約が完全に決定してない場合は常にfalseが返ることに注意)。

hasAmbiguousLayout

曖昧な制約を持ったUIViewクラスは、exerciseAmbiguityInLayout()を実行することで、制約を満たす範囲で制約を変更してくれます。ただ、これはランダムに制約を変更されるので、デバックなどで使用するくらいがいいと思います。

exerciseAmbiguityInLayout()

subviewsに対してhasAmbiguousLayoutを使用することでUIViewクラスやUIVIewControllerクラス単位で簡単なテストをすることも可能になります。

UIViewExtension
extension UIView {
    var isAmbiguousLayout: Bool {
        var isAmbiguous = false
        let views = [self] + subviews
        views.forEach { view in
            if view.hasAmbiguousLayout {
                isAmbiguous = true
                print(view.description)
            }
        }
        return isAmbiguous
    }
}
func testAutolayout() {
    let viewController = SampleViewController.make()
    XCTAssertFalse(viewController.view.isAmbiguousLayout)   
}

制約の出力

コンフリクトした制約

コンフリクトした制約はコンソールにて確認できますが、Identifierを使用することで即座にコンフリクトした制約を確認することができます。storyboard(xib)上でidentifierを設定する方法とコードで設定する二通りの方法があります。

@IBOutlet weak var constraint: NSLayoutConstraint!
...
constraint.identifier = "constraint1"

スクリーンショット 2017-07-24 0.36.00.png

実際に次のような制約のコンフリクトが発生している場合、コンソールには次のエラーログが出力されます。

スクリーンショット 2017-07-24 0.35.11.png

Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x6000000846a0 'topConstant1' V:[_UILayoutGuide:0x7f8c07f05f40]-(50)-[UILabel:0x7f8c07c0b4a0'Label']   (active)>",
    "<NSLayoutConstraint:0x600000084920 'topConstant2' V:[_UILayoutGuide:0x7f8c07f05f40]-(100)-[UILabel:0x7f8c07c0b4a0'Label']   (active)>"
)

実際にコンフリクトしている制約は、かっこの中の部分です。<クラス名:メモリアドレス名 'identifier' レイアウト概要>が出力されるようになっています。通常の画面では複数のコンポーネントがあることが多いので、積極的にidentifierをつけるのがいいかなと思っています。

制約の取得

UIViewクラスがもつconstraintsでviewがもつ制約が配列で取得可能ですが、constraintsAffectingLayout(for:)では、水平方向、垂直方向の制約を指定して取得することができます。

ブレイクポイントの設定

また、制約のエラーはUIViewAlertForUnsatisfiableConstraintsのシンボリックブレイクポイントによって捉えることができます。
Autolayout Breakpoints
に詳しい記述があります。デバッカーコマンドの_autolayoutTraceというメソッドはObjective-Cのプライベートメソッドになるので、ブリッジを定義すればコード上からも実行することが可能です。

ビューデバッカーから制約を確認する

ビューデバッカー上で制約を確認することも可能です。実際にデバックしている制約を確認できるので頻繁に利用しています。

方法はビューデバッカーモードの状態から、画像の青いボタンのShow Constraintボタンを選択し、対象のオブジェクトを選択するだけです。
スクリーンショット 2017-07-24 1.14.45.png

実際に表示された画面が次のようになります。

スクリーンショット 2017-07-24 1.15.27.png

制約を選択すると制約の詳しい情報が見れるので、実際に表示されてる制約が正しいかここで確認するようにしています。

スクリーンショット 2017-07-24 1.15.40.png

23
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
19