[SwiftUI] appDelegate を使ってイベント対応する方法

SwiftUI2021

App の Life Cycle で SwiftUI を選択して作成したプロジェクトで、ApplicationDelegate を使って、イベント対応する方法を説明します。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Monterery beta 3
  • Xcode 13 beta3
  • iOS 15 beta

ApplicationDelegate

App の Life Cycle で "UIKit" や "AppKit" を選択すると、テンプレートとして作成されるクラスです。

iOS 向けであれば、UIApplicationDelegate, macOS 向けであれば、NSApplicationDelegate が実際のクラスです。

UIApplicationDelegate は、こちら

NSApplicationDelegate は、こちら

例えば、UIApplicationDelegate では以下のようなメソッドを用意することで、それぞれに対応するイベントに対処することができるようになります。

  • applicationDidBecomActive -> アプリが active になった後
  • applicationWillResignActive -> active だったアプリが inactive になる時
  • applicationDidEnterBackground -> アプリが、background になった時
  • ....

SwiftUI にも、Life Cycle 関連として、いくつか処理できますが、iOS14, macOS11 時点では、ApplicationDelegate を使用しないと対応できないイベントが多くあります。

SwiftUI での Life Cycle

Environment に scenePhase が定義されていて、scene の変更を検知することができます。scenePhase は、"active", "inactive", "background" の値を取ります。


 @Environment(\.scenePhase) private var scenePhase

他にも補足したいイベントがある時には、scenePhase ではなく、ApplicationDelegate を使用して対応する必要があります。

Life Cycle に "SwiftUI" を選択していても、ApplicationDelegate を使って、イベント対応できるようにする方法があります。

以下では、iOS 向けに、UIApplicationDelegate を使用する方法を説明しますが、UI -> NS と置き換えてもらえれば、macOS にも適用できます。

UIApplicationDelgateAdapator

UIApplicationDelgateAdapator という property wrapper が用意されています。

Apple のドキュメントは、こちら

以下のように使用します。


// (1)
class MyAppDelegate: NSObject, UIApplicationDelegate {
    // (2)
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print("didFinishLaunch")
        return true
    }
    // (2')
    func applicationWillTerminate(_ application: UIApplication) {
        print("willTerminate")
    }
}

@main
struct MyApp: App {
    // (3)
    @UIApplicationDelegateAdaptor(MyAppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
コード解説
  1. UIApplicationDelegate に準拠する class を定義します。このクラスに必要な イベントに対応したメソッドを実装します。
  2. 起動終了時(didFinishLaunching) と 終了時(WillTerminate) にそれぞれのメソッドが呼ばれます。
  3. property wrapper UIApplicationDelegateAdapator で AppDelegate として使用したいクラスのタイプ(ここでは MyAppDelegate)を指定して宣言することで、該当クラスのインスタンスが作成され、AppDelegate として、適宜呼ばれます。

まとめ:SwiftUI Life Cycle で ApplicationDelegate を使う

SwiftUI Life Cycle で ApplicationDelegate を使う
  • @UIApplicatioNDelegateAdaptor で ApplicationDelegate に使用するクラスのタイプを指定して宣言する
  • UIApplicationDelegate に準拠する class に、イベントに対応したメソッドを実装する

@UIApplicationDelegateAdaptor と @State 等の初期化順序に注意してください。
SwiftUI[SwiftUI] @StateObject と @UIApplicationDelegateAdaptor の初期化順

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です