用 NSApplicationDelegateAdaptor 在 SwiftUI 處理 AppKit 的 AppDelegate。
在 SwiftUI 中使用 AppKit 的 AppDelegate
在以 SwiftUI 為主要框架的專案中,如果要使用 AppKit 的 app delegate,要先定義一個遵從 NSApplicationDelegate protocol 的 class,並在裡面實作我們需要用到的 delegate methods。舉例來說,我們可以實作 application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
在成功註冊 Apple Push Notification service(APNs)時做某件事。
class MyAppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
func application(
_ application: NSApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
// Record the device token.
}
}
在定義完 AppDelegate 之後,就可以在 App 底下,使用 NSApplicationDelegateAdaptor property wrapper 來告訴 SwiftUI 我們的 AppDelegate 型別:
@main
struct MyApp: App {
@NSApplicationDelegateAdaptor private var appDelegate: MyAppDelegate
var body: some Scene { ... }
}
這裡可能會覺得奇怪,因為我們並沒有在宣告時就 init AppDelegate,而只告訴它型別,其實 SwiftUI 會自己建立 AppDelegate,並在對應的生命週期裡去呼叫 delegate methods。
注意
盡可能不使用 AppKit 的 app delegate 來處理 app 的生命週期事件,而應優先使用 SwiftUI 自身提供的。如:優先使用 ScenePhase
,而非使用 delegate callback application(_:didFinishLaunchingWithOptions:)
。
ObservableObject:macOS 11.0+
如果我們定義的 AppDelegate 像上面的例子一樣遵從了 ObservableObject protocol,那 SwiftUI 就會把這個 delegate 放進 Environment 裡,我們可以在任何 Scene、任何 View 裡,用 Environment property wrapper 去取得 AppDelegate:
@EnvironmentObject private var appDelegate: MyAppDelegate
如果我們在自己定義的 AppDelegate 中有用到 @Published 的話,就可以直接使用錢字號($)來拿到 binding。
Observable:macOS 14.0+
相對於 ObservableObject,Observable 是比較新的 protocol,效果一樣,但不再需要使用 @Published。要從 Environment 中拿到遵從 Observable 的 AppDelegate 方法如下:
@Environment(MyAppDelegate.self) private var appDelegate
我們也可以直接使用錢字號($)來拿到 AppDelegate 中變數的 binding。
關於 XcodeProject
XcodeProject 創立於 2023,致力於協助開發者探索 Apple 的創新世界,學習在 iOS、iPadOS、macOS、tvOS、visionOS 與 watchOS 上開發 App,發現眾多技術與框架,讓開發者獲得更多能力。