App关闭状态下如何处理LocalNotification?已尝试现有方案无效
Hey there! Let’s work through your notification problems together. I know you’ve dug through existing solutions without success, so let’s break down what’s going wrong and how to fix it.
First, let’s clarify your core issue: Your local notifications (sent with userInfo) work perfectly when the app is in the foreground, but your custom logic isn’t firing when the app is in the background or inactive. You also mentioned a partial remote notification handler, so I’ll cover that too.
1. Fixing Local Notification Handling
The application(_:didReceive:) method you’re using was deprecated in iOS 10—this is likely part of the problem! Apple now recommends using the UNUserNotificationCenterDelegate APIs for all notification handling, which are more reliable for both foreground and background scenarios.
Step 1: Set Up Notification Permissions & Delegate
First, update your AppDelegate to request permissions and set the notification center delegate:
import UserNotifications func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Request necessary notification permissions UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in if let error = error { print("Permission request failed: \(error.localizedDescription)") } } // Assign the delegate to handle notifications UNUserNotificationCenter.current().delegate = self return true }
Step 2: Implement Delegate Methods
Add these extension methods to AppDelegate to handle both foreground notifications and background notification taps:
extension AppDelegate: UNUserNotificationCenterDelegate { // Handle notifications when the app is IN THE FOREGROUND func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { // Add your foreground-specific logic here (like updating UI or showing an alert) // Tell iOS how to present the notification (alert, sound, etc.) completionHandler([.alert, .sound]) } // Handle notifications when the user TAPS THEM (app in background/inactive) func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo // This is where your custom logic goes—like navigating to a specific screen or updating data // My implementation // Always call completionHandler to let iOS know you’re done processing completionHandler() } }
If You Need iOS 9 Compatibility
If your app still supports iOS 9, adjust your old handler to make sure it triggers correctly in the background:
func application(_ application: UIApplication, didReceive notification: UILocalNotification) { // If you already handle foreground notifications elsewhere, keep this check if application.applicationState == .active { // Optional foreground logic here return } // Your background/inactive notification logic // My implementation // Reset badge count if needed application.applicationIconBadgeNumber = 0 }
Double-check that your local notification has alertAction, soundName, and other required properties set, and that the user has granted notification permissions.
2. Completing Remote Notification Handling
You mentioned a partial remote notification handler—here’s how to implement it properly for both iOS 10+ and older versions:
iOS 10+ Remote Notifications
Use the same UNUserNotificationCenterDelegate methods as local notifications, just add a check for the aps payload:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo if let aps = userInfo["aps"] as? [String: Any] { // Remote notification foreground logic completionHandler([.alert, .sound]) } else { // Local notification foreground logic completionHandler([.alert, .sound]) } } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo if let aps = userInfo["aps"] as? [String: Any] { // Remote notification tap logic // My implementation } else { // Local notification tap logic // My implementation } completionHandler() }
iOS 9 & Older Remote Notifications
Use this dedicated handler:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { // Remote notification processing logic // My implementation // Tell iOS the result of your processing completionHandler(.newData) }
3. Critical Checks to Ensure Everything Works
- Permissions: Make sure you’ve requested and received
alert,sound, andbadgepermissions from the user—no permissions = no notifications. - Background Modes: If you need to process notifications while the app is in the background (like silent notifications), enable
Remote notificationsin your app’sBackground Modesunder Xcode’s Capabilities tab. - Completion Handlers: Never forget to call
completionHandlerin iOS 10+ delegate methods—failing to do so can break future notification delivery.
内容的提问来源于stack exchange,提问作者Rafaela Lourenço

