constraint を動的に追加 / 削除する

AutoLayout でレイアウトに必要な constraint を追加する場合、 Storyboard 上で指定する方法と、コードで指定する方法があります。
Storyboard では静的な constraint であれば簡単に追加できますが、動的に追加、そして削除したい場合には、コードで指定しなければならないと思います。

以下では、対象の constraint はつくられているとして、その constraint を動的に追加 / 削除する方法を記述します ( iOS8 以上) 。

方法は、メソッドによる指定とプロパティによる指定の 2 通りがあります。

メソッドによる指定

これらのメソッドは、引数に [NSLayoutConstraint] をとるため、複数の constraint を 1 行で指定することができます。

let constraints = [hogeConstraint, fugaConstraint]

NSLayoutConstraint.activateConstraints(constraints) // constraint の追加

NSLayoutConstraint.deactivateConstraints(constraints) // constraint の削除

プロパティによる指定

単一の constraint を指定する場合にはこちらの方法で良いかと思います。
個人的にはこちらの方が読みやすくて好きです。

hogeConstraint.active = true // constraint の追加

hogeConstraint.active = false // constraint の削除

注意点

注意したいのは、 削除した constraint を再び追加する場合です。
具体的には、 Stroyboard 上で指定した constraint を IBOutlet で接続し、それを状況に応じて削除、そして再び追加するということをしたい場合です。

このとき、constraint の参照を weak として IBOutlet で接続してしまうと、削除したのちに再び追加しようとするとエラーになってしまいます。

@IBOutlet internal var hogeConstraint: NSLayoutConstraint! // weak 参照

hogeConstraint.active = false 

hogeConstraint.active = true // 実行時エラーになる

このエラーを解消するためには、 参照を strong にする必要があるようでした。

@IBOutlet internal var hogeConstraint: NSLayoutConstraint! // strong 参照

hogeConstraint.active = false 

hogeConstraint.active = true // エラーにならない

追記

strong にする必要があると書きましたが、強参照にすると循環参照の恐れがあるので、weak のままで true にする直前にフォースアンラップ等で nil チェックをする方が良さそうかなという気がしています。

参照

tomoyaonishi.hatenablog.jp