在 SwiftUI 中,传统的 AppDelegate
已被简化的生命周期模型替代,但如果你需要访问应用级事件(如推送通知、生命周期回调等),可以通过以下方式集成 AppDelegate
:
1. SwiftUI 中启用 AppDelegate
的步骤
a. 创建自定义 AppDelegate
类
import UIKit
class CustomAppDelegate: NSObject, UIApplicationDelegate {
// 实现需要的 AppDelegate 方法
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("App 启动完成")
return true
}
// 示例:处理推送通知注册
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("设备 Token: \(deviceToken)")
}
}
b. 在 SwiftUI App 中注入 AppDelegate
import SwiftUI
@main
struct MyApp: App {
// 通过 @UIApplicationDelegateAdaptor 注入 AppDelegate
@UIApplicationDelegateAdaptor(CustomAppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
2. 关键点解析
a. @UIApplicationDelegateAdaptor
- 作用:将 UIKit 的
UIApplicationDelegate
桥接到 SwiftUI 应用生命周期。 - 限制:一个应用只能有一个
AppDelegate
。
b. NSObject
和协议继承
-
CustomAppDelegate
必须继承NSObject
(UIKit 要求)。 - 实现
UIApplicationDelegate
协议中的方法。
3. 常见使用场景
a. 处理应用生命周期事件
// 应用进入后台
func applicationDidEnterBackground(_ application: UIApplication) {
print("应用进入后台")
}
// 应用即将终止
func applicationWillTerminate(_ application: UIApplication) {
print("应用即将终止")
}
b. 配置第三方服务
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// 初始化 Firebase
FirebaseApp.configure()
// 配置推送通知
UNUserNotificationCenter.current().delegate = self
return true
}
c. 处理深层链接 (URL Schemes)
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
print("接收到 URL: \(url.absoluteString)")
return true
}
4. 混合生命周期注意事项
a. 与 SwiftUI 生命周期的共存
- SwiftUI 的
ScenePhase
可以监听应用状态,但与AppDelegate
不冲突:@Environment(\.scenePhase) var scenePhase var body: some Scene { WindowGroup { ContentView() } .onChange(of: scenePhase) { newPhase in if newPhase == .background { print("SwiftUI 检测到进入后台") } } }
b. Info.plist
配置
- 如果遇到
AppDelegate
未被调用,检查Info.plist
是否包含Principal class
:<key>NSPrincipalClass</key> <string>$(PRODUCT_MODULE_NAME).CustomAppDelegate</string>
5. 完整代码示例
CustomAppDelegate.swift
import UIKit
import UserNotifications
class CustomAppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// 请求推送通知权限
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, _ in
if granted {
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
}
}
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print("设备 Token: \(token)")
}
}
MyApp.swift
import SwiftUI
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(CustomAppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
6. 迁移旧项目到 SwiftUI
若从 UIKit 迁移到 SwiftUI 并保留 AppDelegate
:
- 保留原有的
AppDelegate
类。 - 在 SwiftUI 入口文件中通过
@UIApplicationDelegateAdaptor
注入。 - 移除
AppDelegate
中与 SwiftUI 冲突的逻辑(如window
管理)。
总结
在 SwiftUI 中集成 AppDelegate
的关键是通过 @UIApplicationDelegateAdaptor
桥接 UIKit 的生命周期,适用于需要处理系统级事件或兼容旧代码的场景。确保遵循 UIKit 的协议要求,并在 Info.plist
中正确配置,即可无缝混合使用 SwiftUI 和传统 AppDelegate 功能。