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

非AppDelegate中请求远程通知后,通知回调未触发的解决方法

问题:引导页授权通知后,AppDelegate的通知响应方法无法触发

需求与当前实现

需求:在OnboardingViewController中,用户点击「允许通知」按钮后发起推送通知授权请求。

当前OnboardingViewController实现代码:

class OnboardingViewController: UIViewController, UNUserNotificationCenterDelegate {

    func registerForRemoteNotification() {
            
        let center  = UNUserNotificationCenter.current()

        center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
            if error == nil && granted {
                print("Brugeren har accepteret notifikationer")
                DispatchQueue.main.async {
                    UNUserNotificationCenter.current().delegate = self
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
            
        }
        
    }
}

遇到的问题

采用上述实现时,AppDelegate中的以下通知响应方法无法被调用:

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        
    print("Test 1")
         
    completionHandler()
}

只有将授权请求代码放到AppDelegate的didFinishLaunchingWithOptions方法中,该didReceive方法才会正常执行。


问题原因

核心问题是**UNUserNotificationCenter的代理被设置为OnboardingViewController实例,但当引导页完成使命被销毁(比如用户跳转至主页面),该代理对象会被释放,导致后续通知事件无法传递到AppDelegate**。

你在授权成功后将代理指向了当前的OnboardingViewController,而AppDelegate虽然实现了代理方法,但从未被设置为通知中心的代理,因此引导页销毁后,通知中心没有有效代理处理事件,自然触发不了AppDelegate中的方法。


解决方案

方案一:将AppDelegate设置为全局代理

修改OnboardingViewController中的授权代码,把通知中心的代理指向AppDelegate实例,而非当前控制器:

func registerForRemoteNotification() {
        
    let center = UNUserNotificationCenter.current()

    center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
        if error == nil && granted {
            print("Brugeren har accepteret notifikationer")
            DispatchQueue.main.async {
                // 获取AppDelegate实例并设置为通知中心代理
                let appDelegate = UIApplication.shared.delegate as! AppDelegate
                UNUserNotificationCenter.current().delegate = appDelegate
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
}

同时确保AppDelegate已遵守UNUserNotificationCenterDelegate协议:

@main
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    // ... 其他原有代码
}

方案二:创建独立的通知管理单例(推荐)

为避免页面控制器与AppDelegate耦合,更优雅的方式是创建全局单例统一管理通知逻辑:

class NotificationManager: NSObject, UNUserNotificationCenterDelegate {
    static let shared = NotificationManager()
    
    private override init() {
        super.init()
        // 初始化时就将自身设为通知中心代理
        UNUserNotificationCenter.current().delegate = self
    }
    
    func requestNotificationAuthorization() {
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
            if error == nil && granted {
                print("Brugeren har accepteret notifikationer")
                DispatchQueue.main.async {
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
        }
    }
    
    // 实现通知响应方法
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        print("Test 1")
        completionHandler()
    }
    
    // 可选:处理前台收到通知时的展示逻辑
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.sound, .alert, .badge])
    }
}

之后在OnboardingViewController中直接调用单例方法即可:

func registerForRemoteNotification() {
    NotificationManager.shared.requestNotificationAuthorization()
}

这种方式将通知逻辑集中管理,不受页面生命周期影响,后续扩展通知功能也更便捷。


内容的提问来源于stack exchange,提问作者M. Holm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 06:10:39