はじめに
UIKitを使用したiOSアプリ開発を学ぶ際、多くの初心者向け教材はUIの実装方法に焦点を当てています。
しかし私は、アプリケーションの基本的な制御フローを理解することが、今後UIを自身で実装することができる重要な要素だと思います!
この記事では、UIKitを使用したiOSアプリの起動から最初の画面表示までの流れを詳しく解説します。AppDelegate、SceneDelegate、StoryboardそしてViewControllerがどのように連携して動作するのか、理解することが目標です!
対象読者
- UIKitでプロダクト開発したい方!
- UIKitの制御フローを把握したい方!
環境
- Swift version 5.10
- Xcode version 15.3
プロジェクト作成
前回と同様に、Interface に Storyboard を選択してプロジェクトを作成します。
構成の確認
XCodeが提供してくれるテンプレートは、あらゆるアプリ制作の基盤として利用できます。
template を iOS app を選択した場合、最初のフォルダ構成は下記のようになります。
各ファイルの概要は以下の通りです。
- AppDelegate.swift : アプリケーションのライフサイクルを管理
- SceneDelegate.swift : UISceneSessionのライフサイクルを管理(iOS 13以降)
- ViewController.swift : 画面のコンテンツと動作を管理
- (補足: UIKitフレームワークで定義された、UIViewContollerを継承している。)
- Main.storyboard : ユーザーインターフェースのビジュアルレイアウト
- LaunchScreen.storyboard : アプリ起動時に表示される画面
- Assets.xcassets: 画像やアイコンなどのリソースを管理
- Info.plist : アプリの設定情報を含む
コードの追加と動作確認
アプリの起動フローに関して詳しく説明する前に、ViewControlerにコード追加し、画面上にテキストが表示されることを確認してみます!
コードの追加
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// ラベルのインスタンスを生成
let label = UILabel()
// ラベルのサイズと位置を設定
label.frame = CGRect(x: 350, y: 100, width: 500, height: 100)
// 表示テキスト設定
label.text = "Hello, World!"
// 色設定
label.textColor = .red
// フォントサイズ設定
label.font = UIFont.systemFont(ofSize: 30)
// View に UILabel を追加
view.addSubview(label )
}
}
動作確認
コードを追加したので、動作を確認をしましょう!
- build ターゲットを選択
今回は、iOS Simulators から iPhone15Pro を選択。 - 実行
実行ボタンをクリック(または、command + R)で確認。
これでテンプレートの初期設定では、ViewControllerに変更を加えることで表示される内容が変わることを確認できました!
なぜ、ViewControllerを変更すると表示される内容が変わるのでしょうか?
それを理解するために、アプリの起動フローを確認しましょう!
アプリの起動フロー
ここからは、アプリが起動してから、最初の画面が表示されるまでのフローを説明します。
- AppDelegateがアプリケーションの起動を処理
- SceneDelegateがUIWindowとrootViewControllerを設定
- Main.storyboardから最初のViewControllerが読み込まれる
- ViewControllerのviewDidLoad()メソッドが呼ばれる
各項目について、みていきましょう!
1. AppDelegateがアプリケーションの起動を処理
AppDelegateの役割
アプリケーションのライフサイクルイベントを処理する役割があります。アプリの起動、バックグラウンドへの移行、終了など、重要なイベントをここで管理します。
@ main属性
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
AppDelegateクラスの上に @main
と記述されています。これはアプリケーションのエントリーポイントであること、つまり、アプリが起動するとき最初に呼び出されるのがこのクラスであることを示しています。
SecenDelegateに遷移
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
application(_:didFinishLaunchingWithOptions:)メソッドでreturn true
で正常にアプリ起動が完了すると、SecenDelegateに遷移します。
2. SceneDelegateがUIWindowとrootViewControllerを設定
SceneDelegateの役割
アプリの個別のUIWidnow(シーン)のライフサイクルを管理します。
(シーン : アプリはマルチウィンドウをサポートするために「シーン」という概念を導入。各シーンは独立したUIWindowとViewControllerの階層を持つ)
seceneメソッド
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
}
このメソッドは、新しいシーンが作成される時に呼ばれます。ここで、UIWidowの設定とrootViewController(一番最初に読み込まれるUIViewControllerカスタムクラス)指定を行うことができます。ですが、コード上では rootViewController を指定するような処理は実装されていません。
実は、コード上で実装しないでも設定することがでます。
どこでrootViewControllerを指定しているのかは、Storyboardに関わる Info.plistを確認すると分かります。
3. Main.storyboardから最初のViewControllerが読み込まれる
Main.storyboardが読み込まれる理由
各Info.plist の Main storyboard file bace name
と Storyboard Name
を確認すると Main
となっていることが分かります。
この設定により、SecenDelegate の Sceneメソッド
のコード上で実装されていなくても、システムがInfo.plistを参照して Main.storybaord を読み込みます。
(Main storyboard file base nameは、従来の設定で、アプリの主要なストーリーボードファイルを指定するためのものです。Storyboard Nameは、新しいシーンベースのライフサイクルシステム(iOS 13以降)で使用される設定です。同一名にすることで、どのiOSバージョンでも一番最初に呼び込まれるStoryboardを同一にできます。)
Main.storyboard 上でrootViewControllerを設定
Main.storyboard 内の ViewController をクリックして、 Attributes を Inspector上に表示します。そして、ViewController の設定項目を確認します。
Is Initial View Controller
にチェックマークが入っていると、Tittle
と同名のViewControllerを参照します。空白の場合、デフォルトでViewController
という値になります。
これらの設定により、Main.stoaryboard が最初に参照する ViewController を呼び込むことが出来ています!
4. ViewControllerのviewDidLoad()メソッドが呼ばれる
呼び込まれるViewControllerは、UIViewConrollerを継承しています。
UIViewControllerの役割
UIViewControllerは、ユーザーインターフェースの一部を管理し、そのViewのライフサイクルを制御します。
これは、画面上の要素であるUIView(テキストラベルやボタン)らの動作を管理する中心的な場所です。
Viewのライフサイクル
viewDidLoad()メソッドは、ライフサイクルの一部です。(他、viewWillAppear・viewDidAppearなど)
ここで、今回ラベルを追加したように、UIの初期設定などを行います。
まとめ
今回の制御フロー
アプリ起動
↓
SceneDelegateが画面(シーン)の設定
↓
Info.plistの設定に基づいてMain.storyboardが読み込まれる
↓
Main.storyboard内で「Is Initial View Controller」に設定されたViewControllerが最初の画面として表示
↓
ViewControllerのviewDidLoad()メソッドが実行され、画面の内容が初期化される。
↓
作成したラベル(「Hello, World!)が画面上に表示される
最後に
本記事では、UIKitを使用したiOSアプリケーションの起動から画面表示までの基本的な制御フローを解説しました。
この制御フローを理解することで、アプリケーションの動作の仕組みがより明確になります。
次回は、ViewControllerのライフサイクルについてより詳しく解説し、UIKitを使用したアプリ開発の理解をさらに深めていけたらと思います。
[次の項目] 執筆中