Help us understand the problem. What is going on with this article?

Autolayout tips for iOS

More than 3 years have passed since last update.

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

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

shoheiyokoyama
【横山 祥平 / @shoheiyokoyama 】 CyberAgent, Inc / AbemaTV / CATS / iOS Engineer Medium: https://medium.com/@shoheiyokoyama
https://github.com/shoheiyokoyama
cyberagent
サイバーエージェントは「21世紀を代表する会社を創る」をビジョンに掲げ、インターネットテレビ局「AbemaTV」の運営や国内トップシェアを誇るインターネット広告事業を展開しています。インターネット産業の変化に合わせ新規事業を生み出しながら事業拡大を続けています。
http://www.cyberagent.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away