Swift NotificationContentExtension不生效:自定义通知UI无法默认显示
问题:自定义通知UI默认不显示,仅长按后加载
我开发的消息应用用OneSignal实现通知功能,已集成标准的OneSignal NotificationServiceExtension。现在需要通过NotificationContentExtension自定义通知UI,将通知左侧的应用图标替换为消息发送者的头像(暂时没找到更简便的实现方式)。
当前问题:通知送达时显示原生推送UI,只有长按通知后才会加载出自定义UI(加载速度较慢),我需要默认直接显示自定义UI。我认为该问题与OneSignal无关,但暂无法脱离它测试。
环境
- iOS 17.0(所有目标版本均为17.0)
代码实现
主应用代码(SwiftUI)
import SwiftUI import OneSignalFramework @main struct qqqqApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() } } class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { if #available(iOS 10.0, *) { let options: UNAuthorizationOptions = [.alert] UNUserNotificationCenter.current().requestAuthorization(options: options) { (authorized, error) in if authorized { let categoryIdentifier = "OSNotificationCarousel" let carouselNext = UNNotificationAction(identifier: "OSNotificationCarousel.next", title: "👉", options: []) let carouselPrevious = UNNotificationAction(identifier: "OSNotificationCarousel.previous", title: "👈", options: []) let carouselCategory = UNNotificationCategory(identifier: categoryIdentifier, actions: [carouselNext, carouselPrevious], intentIdentifiers: [], options: []) UNUserNotificationCenter.current().setNotificationCategories([carouselCategory]) } } } // Remove this method to stop OneSignal Debugging OneSignal.Debug.setLogLevel(.LL_VERBOSE) // OneSignal initialization OneSignal.initialize("API_KEY", withLaunchOptions: launchOptions) // requestPermission will show the native iOS notification permission prompt. // We recommend removing the following code and instead using an In-App Message to prompt for notification permission OneSignal.Notifications.requestPermission({ accepted in print("User accepted notifications: \(accepted)") }, fallbackToSettings: true) return true } }
NotificationServiceExtension代码
import UserNotifications import OneSignalExtension class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var receivedRequest: UNNotificationRequest! var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.receivedRequest = request self.contentHandler = contentHandler self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) if let bestAttemptContent = bestAttemptContent { /* DEBUGGING: Uncomment the 2 lines below to check this extension is executing Note, this extension only runs when mutable-content is set Setting an attachment or action buttons automatically adds this */ // print("Running NotificationServiceExtension") // bestAttemptContent.body = "[Modified] " + bestAttemptContent.body OneSignalExtension.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler) } } override func serviceExtensionTimeWillExpire() { // Called just before the extension will be terminated by the system. // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { OneSignalExtension.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent) contentHandler(bestAttemptContent) } } }
NotificationContentExtension代码
import UIKit import UserNotifications import UserNotificationsUI class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var titleLabel: UILabel? @IBOutlet var subtitle: UILabel? override func viewDidLoad() { super.viewDidLoad() // Do any required interface initialization here. } func didReceive(_ notification: UNNotification) { self.titleLabel?.text = notification.request.content.title self.subtitle?.text = notification.request.content.body } }
NotificationContentExtension的Info.plist配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>NSExtension</key> <dict> <key>NSExtensionAttributes</key> <dict> <key>UNNotificationExtensionDefaultContentHidden</key> <true/> <key>UNNotificationExtensionCategory</key> <string>OSNotificationCarousel</string> <key>UNNotificationExtensionInitialContentSizeRatio</key> <real>0.3</real> </dict> <key>NSExtensionMainStoryboard</key> <string>MainInterface</string> <key>NSExtensionPointIdentifier</key> <string>com.apple.usernotifications.content-extension</string> </dict> </dict> </plist>
内容的提问来源于stack exchange,提问作者f3dm76
相关产品推荐
相关产品推荐

