はじめに
それなりにUIコンポーネントが多いアプリを開発しているときに
親のViweに対して、特定のView(子)を親Viewと同じサイズで目一杯にして貼り付けたいという事がよくあります。(コードで)
数ヶ月前までの自分は、そのたびに、子Viewと親ViewのAutoLayout制約を毎回コードで設定していました。
それがあまりにも非効率だったため、最近はExtensionを使うようにしています。
それと、わざわざAutoLayout制約を設定しなくてもいい方法も見つけたので、記事にしてみました。
よくある具体的な場面
// コードでViewを生成
let childView = UIView()
childView.backgroundColor = .orange
// chilidView(子)をparentView(親)に目一杯貼り付けたい
parentView.addSubView(childView)
UIView+Extension で実装する方法
処理としては、Viewの四方に制約を設定するだけの簡単なコードですが、Extensionで用意せずに、各ViewControllerで毎回実装しようとすると、それだけでFatViewController
になりかねません。(過去の私はなりました)
extension UIView {
// childViewを親Viewに目一杯addSubView()する
func addSubViewFill(_ childView: UIView) {
self.addSubview(childView)
childView.translatesAutoresizingMaskIntoConstraints = false
childView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
childView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
childView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
childView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
}
}
利用するときは、最初から制約が設定されているお得なaddSubView()
という感覚で使ってしまって大丈夫です。
parentView.addSubViewFill(childView)
個人的にはめちゃめちゃ万能なので、重宝しているやり方です。
AutoLayout制約を設定しない方法
override func viewDidLoad() {
parentView.addSubView(childView)
}
override func viewDidLayoutSubviews() {
childView.frame = parentView.bounds
}
こっちの使い時としては、viewDidLoad()
などで、事前にaddSubView
が完了している子ViewのFrameを
viewDidLayoutSubviews()
で、親Viewと同じ大きさに設定してしまう方法です。
viewDidLayoutSubviews()
で設定する理由としては、viewDidLoad()
のときは、親Viewのサイズが正しく取得できないため、各Viewのサイズが正しく取得されるタイミングにて、設定しているということです。
AutoLayout制約をつけなくていいのがこちらのメリットだと思います。
ただ、注意点があって
- ユーザーの操作や画面描画後の特定の条件のときのみ、親Viewに貼り付けたいなどといったときは、
viewDidLayoutSubviews()
に予め処理を設定しにくい。 -
viewDidLayoutSubviews()
は、明示的に呼び出すわけではなく、画面のサイズが変わった時(回転時など)にOSから勝手に呼ばれるので、あまりいろいろなレイアウト設定をするとバグの温床になる。
というデメリットもあると思います。
あまり複雑じゃない画面で、AutoLayout制約が不要なときは、使えると思います。
おわりに
コードでaddSubViewする機会が多いよ。という方は、新規プロジェクトを作ったらすぐにUIViewのExtensionに実装すると良いかもしれませんね。
読んでいただいた方のアプリ開発が少しでも効率化すれば幸いです。
他にこういう方法あるよ!という方がいらしたら是非コメントで教えていただけると嬉しいです。