技術

SwiftのAutoLayoutをコードで書くときの注意点まとめ

どうも、フリーランスのITエンジニア兼ブロガー兼投資家のKerubitoです。

AutoLayoutをコードで書きたい!

なんていうことがたまにあると思います。

直感的にはわかりづらいですが、動的な画面を作る際にはどうしてもStoryBoardでは難しいことがあります。

StoryBoardでもActiveかどうかで切り替えたりできますが、そうなると一気に可読性が悪くなるんですよね。

たまにStoryBoard上で匠の技レベルの制約を見かけますが、非常に見づらい。

それならコードで書いたほうがマシ。

しかし、コードで書くとはまるポイントがいくつかあります。

本記事では自分への備忘録も兼ねて、AutoLayoutをコードで書く際の注意点をまとめてみました。

環境は以下の通りです。

・Swiftバージョン:5
・Xcodeバージョン:11.6
・使用デバイス:iPhone8(14.2)

AutoLayoutをコードで書くときの参考になれば幸いです。

Does the constraint or its anchors reference items in different view hierarchies?  That's illegal.

制約を入れて、ビルドも通って、いざ実行。

すると以下のようなエラーが出ます。

'Unable to activate constraint with anchors <NSLayoutXAxisAnchor:0x283011100 "***.centerX" (names: ***:0x10ca14980)> and <NSLayoutXAxisAnchor:0x283016a40 "***.CustomWindow:0x105f1a850.centerX"> because they have no common ancestor.  Does the constraint or its anchors reference items in different view hierarchies?  That's illegal.'

適当に訳すと「そんなオブジェクトはいないけど、なんか階層とか間違ってんじゃねえの?」ってなことを言っています。

そんなわけないだろうと思いますが、コードは以下。

原因は制約を追加する前にaddSubviewしないと、オブジェクトがないって怒られるんですね。

制約を入れた部品が表示されない

上のソースのままだと、UILabelは表示されません。

label.frame = self.view.frame

といった感じで制約を入れる前に一度frameを設定しないといけないようです。

制約を入れた部品が正しく表示さえない

なぜかちゃんと指定しているはずの制約が正しく効かない。

ということがたまにあります。

原因の一つがtranslatesAutoresizingMaskIntoConstraintsというプロパティです。

translatesAutoresizingMaskIntoConstraintsはAuto Layout以前に使われていた、Autosizingという仕組みをAuto Layoutに変換するかどうかを設定するフラグです。

デフォルトはオンなのですが、このままだと制約が正しく効かない場合があります。

なので

label.translatesAutoresizingMaskIntoConstraints = false

といった感じでオフにしておきましょう。

AutoLayoutをコードで書くときの正しい例

最後に上のコードでいう正しい例を載せておきます。

楽しい開発ライフを!

-技術

© 2021 Kerubitoのブログ