【Swift/UIKit】UIViewControllerの役割とは?ビュー階層とviewDidLoadメソッド
この記事からわかること
- Swift/UIKitのViewControllerとは?
- UIViewControllerクラスの役割
- ビュー階層構造の仕組み
- viewプロパティやviewDidLoadメソッドとは?
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
iOSアプリを開発する言語SwiftのUIKitフレームワークで遭遇するUIViewController
とはどのようなものか自分なりにまとめていきます。
MVCアーキテクチャ
UIKitフレームワークはMVCアーキテクチャに倣って設計されており、UIViewController
はその中の「C:Controller」に該当します。Controllerの役割はそれぞれが別々で定義されているModel(データ)とView(画面)を紐付けることです。
MVCアーキテクチャの3要素
- Model(モデル):データそのもの:Data
- View(ビュー):表示される画面:UIView
- Controller(コントローラ):MとVを操作する:UIViewController
おすすめ記事: Swift(UIKit)のMVCアーキテクチャーとは?役割と構造まとめ
UIViewControllerクラスの役割
公式リファレンス:The Role of View Controllers
UIViewControllerクラスの役割はUIKitフレームワークにおけるアプリのビュー階層を管理するためのクラスです。
具体的には以下のような「Root view」を大元にした階層構造で構築されたビューを管理しており、このRoot viewに対してUI部品を追加していくことで1つの画面を作り上げていきます。
またビュー階層の管理以外にもイベント処理や画面遷移/連携などの役割も持っており、アプリを構築する上で中心的な役割を持つクラスになります。
UIViewクラス
おすすめ記事: 【Swift/UIKit】UIViewクラスとは?使い方やプロパティまとめ
var view: UIView!
UIViewControllerクラスは必ず1つの画面(ビュー:Root view)と紐づいています。その画面(ビュー:Root view)はUIView
型のview
プロパティとして管理されています。
UIView
クラスはあらゆるUI部品の親クラスであり、画面に矩形を表示(レンダリング)する機能とビューの階層構造を管理する機能を持っています。
あらゆるUI部品の親クラス
UIButtonやUILabel、UIPickerView、UITextFieldといった様々なUI部品はUIViewクラスを拡張することで定義されています。
画面に矩形を表示(レンダリング)する機能
画面に対して矩形(長方形)でビューを表示します。
ビューの階層構造を管理する機能
ビューのZ軸上の重なりをビューの階層構造として管理しています。ユーザーからみて奥にあるビューをsuper view、手前にあるビューをsub viewと呼びます。
UIViewControllerクラスのライフサイクル
UIViewControllerクラスはviewプロパティが参照された時にloadView
メソッドを呼び出し実際にビューを読み込みます。その後にviewDidLoad
メソッドが呼ばれます。
ライフサイクル
- viewプロパティへの参照を検知
- loadViewメソッドの実行
- viewDidLoadメソッドの実行
viewDidLoadメソッド
func viewDidLoad()
viewDidLoad
メソッドは名前の通り「ビューを読み込んだ後に実行される」メソッドです。このメソッドをオーバーライドして追加するUI部品を定義することで、ボタンやラベルなどのビューを組み込みことができるようになります。
プロジェクト内でのUIViewController
ここからは実際のコードを見ていきます。
UIKitでは新規のプロジェクトを作成したときに様々なファイルが自動生成されその中の「ViewController.swift」内にUIViewController
に準じたクラスが記述されています。
UIKitプロジェクト内のファイル群
├── Swiftプロジェクト
│ ├── プロジェクト名
│ ├── AppDelegate.swift
│ ├── ViewController.swift
│ ├── Main.storyboard
│ ├── Assets.xcassets
│ ├── LaunchScreen.storyboard
│ └── info.plist
│ └── プロジェクト名.xcodeproj
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.(ビューを読み込んだ後、追加の設定を行います。)
}
}
UIKitフレームワークを使用したiOSアプリ開発ではこのViewControllerクラスを起点にビューを構築します。
UI部品を追加する
ビュー(画面)に対してUI部品を追加するにはUI部品のインスタンスを生成し、明示的に表示位置を指定する必要があります。定義したUI部品はaddSubview
メソッドを使ってビューに追加します。
class ViewController: UIViewController {
let label = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
let screenWidth = self.view.frame.width
let screenHeight = self.view.frame.height
label.text = "Hello World!!"
label.frame = CGRect(x:screenWidth/3, y:screenHeight/2,width:screenWidth/2, height:30)
self.view.addSubview(label)
}
}
画面内の表示位置とサイズはUIView
のframe
プロパティにCGRect
型で指定できます。
iOSデバイスは以下画像のように左上を(x:0,y:0)
としたX軸/Y軸として管理されているので長方形を表示する座標情報が必要になってきます。
おすすめ記事:【Swift】CGRectの使い方!Core Graphicsとは?
ビュー階層
addSubview
メソッドが指定したビューのsubviewとして追加するメソッドなので、後から追加したものが一番手前に配置されます。superviewと同じ座標にある場合は、上に重なります。
class ViewController: UIViewController {
let label = UILabel()
let label2 = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
let screenWidth = self.view.frame.width
let screenHeight = self.view.frame.height
label.text = "Hello World!!"
label.backgroundColor = .orange
label2.text = "こんにちは 世界!!"
label2.backgroundColor = .darkGray
label.frame = CGRect(x:screenWidth/3, y:screenHeight/2,
width:screenWidth/2, height:30)
label2.frame = CGRect(x:screenWidth/3, y:screenHeight/2,
width:screenWidth/4, height:20)
self.view.addSubview(label) // 奥側
self.view.addSubview(label2) // 手前側
}
}
ビュー関連のイベント駆動メソッド
ビューが追加や削除された時のイベント駆動で実行されるメソッドも用意されています。これは最初の読み込み時ではなく、モーダルビューなどの後発的な変化に合わせて駆動します。
// ビューがビュー階層に追加されようとしていることをView Controllerに通知
func viewWillAppear() {
print("追加されるよ")
}
// ビューがビュー階層に追加されたことをView Controllerに通知
func viewDidAppear() {
print("追加されたよ")
}
// ビューがビュー階層から削除されようとしていることをView Controllerに通知
func viewWillDisappear() {
print("削除されるよ")
// isMovingFromParentで完全に取り除かれようとしているかどうかを検知できる
if isMovingFromParent {
// ビューコントローラがナビゲーションスタックからポップされたり、親から取り除かれてた場合
} else {
// タブなどで切り替わって非表示になった時はこっち
}
}
// ビューがビュー階層から削除されたことをView Controllerに通知
func viewDidDisappear() {
print("削除されたよ")
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。