You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中无法将AppDelegate本地通知信息传递至视图

问题:本地通知信息无法传递到SwiftUI的MainView

已配置好可正常触发的本地通知,想要从中提取信息并跳转至指定视图,但目前无法将通知信息传递到MainView的onReceive代码块中。能在AppDelegate的代码中看到通知内容,推测遗漏了关键步骤,核心需求是将AppDelegate中的通知信息传递到MainView。

原代码

@main
struct UntitledNewsApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @StateObject var notificationData = NotificationData()
    
    
    var body: some Scene {
        WindowGroup {
            MainView()
                .environmentObject(notificationData)
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    var notificationData = NotificationData()
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        return true
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        // Handle the received notification and navigate to the desired view
        if response.actionIdentifier == UNNotificationDefaultActionIdentifier {
            let articleResponse = response.notification.request.content
            
            notificationData.notificationTitle = articleResponse.title
            
            DispatchQueue.main.async {
                if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
                    appDelegate.notificationData.notificationTitle = articleResponse.title
                }
            }
            // Notification tapped, navigate to the desired view
            NotificationCenter.default.post(name: NSNotification.Name("NotificationTapped"), object: nil)
        }
        
        completionHandler()
    }
}

class NotificationData: ObservableObject {
    @Published var notificationTitle: String = ""
}

struct MainView: View {
    @EnvironmentObject var notificationData: NotificationData
    // ... 其他代码
    var body: some View {
        Text("Never Give You Up")
            .onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("NotificationTapped"))) { notification in
                print("onReceive in blank: \(notificationData.notificationTitle)")
            }
    }
}

问题根源

你在AppDelegate中创建了一个独立的NotificationData实例,而MainView使用的是App中@StateObject创建的另一个实例——两者是完全独立的对象,因此AppDelegate中修改的通知信息无法同步到MainView的环境对象中。

修复方案

修改核心点

  1. 移除AppDelegate中私有的NotificationData实例,改为引用App中共享的实例
  2. 在App启动时,让AppDelegate获取到App中的notificationData
  3. 确保在主线程更新ObservableObject数据(通知回调可能在后台线程执行)
  4. 先更新数据再发送通知,保证onReceive触发时数据已同步

修改后的完整代码

@main
struct UntitledNewsApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @StateObject var notificationData = NotificationData()
    
    var body: some Scene {
        WindowGroup {
            MainView()
                .environmentObject(notificationData)
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    // 改为引用共享的NotificationData实例
    private var sharedNotificationData: NotificationData?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        // 获取App中共享的NotificationData实例
        if let app = application.delegate as? UntitledNewsApp {
            sharedNotificationData = app.notificationData
        }
        return true
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        guard response.actionIdentifier == UNNotificationDefaultActionIdentifier else {
            completionHandler()
            return
        }
        
        let articleResponse = response.notification.request.content
        
        // 在主线程更新共享数据,再发送通知
        DispatchQueue.main.async {
            self.sharedNotificationData?.notificationTitle = articleResponse.title
            NotificationCenter.default.post(name: NSNotification.Name("NotificationTapped"), object: nil)
        }
        
        completionHandler()
    }
}

class NotificationData: ObservableObject {
    @Published var notificationTitle: String = ""
}

struct MainView: View {
    @EnvironmentObject var notificationData: NotificationData
    // ... 其他代码
    var body: some View {
        Text("Never Give You Up")
            .onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("NotificationTapped"))) { _ in
                print("onReceive in blank: \(notificationData.notificationTitle)")
            }
    }
}

额外优化建议

  • 可以给通知名称定义一个全局常量,避免硬编码字符串:
    extension Notification.Name { 
        static let notificationTapped = Notification.Name("NotificationTapped") 
    }
    
    使用时直接写.notificationTapped即可。
  • 如果只需要通过@Published属性的变化来触发视图更新,甚至可以去掉NotificationCenter的使用,直接在MainView中监听notificationTitle的变化:
    .onChange(of: notificationData.notificationTitle) { newTitle in
        if !newTitle.isEmpty {
            print("Notification title updated: \(newTitle)")
            // 这里执行跳转逻辑
        }
    }
    

内容的提问来源于stack exchange,提问作者Robert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:04:55