Swift中iOS 10以下系统如何调用通知响应接收方法?
Got it, let's tackle this backward compatibility issue for your notification tap handling. Your current code works great for iOS 10+, but we need to add support for iOS 9 and earlier where the notification system works a bit differently.
Key Background for iOS <10
On older iOS versions, notification tap events aren’t managed by UNUserNotificationCenterDelegate—instead, they’re routed directly through UIApplicationDelegate methods. Also, if your app is launched directly from a notification (cold start, not running in the background), you’ll need to check the launch options to handle that scenario too.
Step 1: Add Delegate Methods for iOS <10
Add these methods to your main AppDelegate class (outside the iOS 10+ extension) to handle both remote and local notification taps:
// Handle remote notification taps (iOS <10) func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { handleNotificationTap(userInfo: userInfo) } // Handle remote notification taps with background fetch support (iOS <10) func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { handleNotificationTap(userInfo: userInfo) completionHandler(.noData) // Adjust this based on your app's background needs } // Handle local notification taps (iOS <10) func application(_ application: UIApplication, didReceive notification: UILocalNotification) { if let userInfo = notification.userInfo { handleNotificationTap(userInfo: userInfo) } } // Centralized helper to reuse notification tap logic private func handleNotificationTap(userInfo: [AnyHashable: Any]) { // Reuse your existing logic from the iOS 10+ delegate method print("Notification tapped (iOS <10)") if let fromValue = userInfo["customParameterKey_from"] as? String { print(fromValue) } // Add your custom action here (e.g., navigate to a specific screen) }
Step 2: Handle Cold Start from Notifications (iOS <10)
When the app is launched directly from a notification (wasn’t running in the background), you need to process the notification data in didFinishLaunchingWithOptions. Update that method with these checks:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // ... your existing authorization code ... // Check if app was launched from a remote notification (iOS <10) if let remoteNotification = launchOptions?[.remoteNotification] as? [AnyHashable: Any] { handleNotificationTap(userInfo: remoteNotification) } // Check if app was launched from a local notification (iOS <10) if let localNotification = launchOptions?[.localNotification] as? UILocalNotification { if let userInfo = localNotification.userInfo { handleNotificationTap(userInfo: userInfo) } } application.registerForRemoteNotifications() return true }
Step 3: Centralize Logic for iOS 10+ (Optional but Recommended)
To keep your code DRY, you can reuse the same handleNotificationTap helper in your iOS 10+ delegate method:
@available(iOS 10, *) extension AppDelegate : UNUserNotificationCenterDelegate { // ... your existing willPresent method ... func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo handleNotificationTap(userInfo: userInfo) // Reuse the centralized logic completionHandler() } }
Full Modified AppDelegate Code
Here’s the complete code with all additions included:
import UIKit import UserNotifications @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. if #available(iOS 10.0, *) { print("we are here 10") // For iOS 10 display notification (sent via APNS) UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: {_, _ in }) } else { print("we are here 9") let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } // Handle cold start from notification (iOS <10) if let remoteNotification = launchOptions?[.remoteNotification] as? [AnyHashable: Any] { handleNotificationTap(userInfo: remoteNotification) } if let localNotification = launchOptions?[.localNotification] as? UILocalNotification { if let userInfo = localNotification.userInfo { handleNotificationTap(userInfo: userInfo) } } application.registerForRemoteNotifications() return true } // Handle remote notification taps (iOS <10) func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { handleNotificationTap(userInfo: userInfo) } // Handle remote notification taps with background fetch support (iOS <10) func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { handleNotificationTap(userInfo: userInfo) completionHandler(.noData) } // Handle local notification taps (iOS <10) func application(_ application: UIApplication, didReceive notification: UILocalNotification) { if let userInfo = notification.userInfo { handleNotificationTap(userInfo: userInfo) } } // Helper to centralize notification tap logic private func handleNotificationTap(userInfo: [AnyHashable: Any]) { print("we are here") if let fromValue = userInfo["customParameterKey_from"] as? String { print(fromValue) } // Add your custom navigation/action logic here } // ... rest of your existing AppDelegate methods ... func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } } @available(iOS 10, *) extension AppDelegate : UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo print(userInfo) completionHandler([]) } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo handleNotificationTap(userInfo: userInfo) completionHandler() } }
This setup ensures:
- Consistent notification tap handling across iOS 9 and iOS 10+
- Proper processing of notifications that launch the app cold
- Clean, centralized logic that’s easy to update and maintain
内容的提问来源于stack exchange,提问作者Nomi

