[英]iOS 10 UNUserNotificationCenterDelegate not called. push notifications not working
撕裂我的頭發,以便在iOS10中使用推送通知。 目前的設置:
在func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
:
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if error == nil {
print("DID REQUEST THE NOTIFICATION")
UIApplication.shared.registerForRemoteNotifications()
}
}
print("DID SET DELEGATE")
}
在func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
:
print("DID REGISTER FOR A REMOTE NOTIFICATION AND THE TOKEN IS \(deviceToken.base64EncodedString())"
let request = UpdatePushNotificationSubscription_Request(deviceToken: deviceToken)
updatePushNotificationSubscriptionWorker.updateSubscription(request)
我已經檢查過令牌是否正確上傳到后端,它確實匹配。
我也實施了:
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("GOT A NOTIFICATION")
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
//This is for the user tapping on the notification
print("GOT A NOTIFICATION")
}
我已為所有目標設置權限並啟用了推送:
現在當我嘗試從后端發送消息時,設備什么都沒有收到。 代表們沒有被召集。 不知道我在這里做錯了什么。 Push適用於iOS9和Android設備。 我可能做錯了什么指針?
這個答案適用於使用UserNotifications
框架的iOS 10+。
您需要一個類符合UNUserNotificationCenterDelegate
協議。 如果您為此創建一個新類,或將其添加到您的AppDelegate
類,則無關緊要。 我建議創建一個專門的課程。 出於本答案的目的,我們假設您為它創建一個UserNotificationController
類。
該類可以具有以下方法:
optional func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
optional func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
然后在AppDelegate.application(_:didFinishLaunchingWithOptions:)
方法中,您需要將UNUserNotificationCenter.current()
對象上的delegate
設置為UserNotificationController
類的實例。 您可能希望使用共享實例。
請求用戶授權以使用UNUserNotificationCenter.requestAuthorization(options:completionHandler:)
方法啟用通知,並在completionHandler
中檢查granted
值。 如果為true
,則通過調用UIApplication.shared.registerForRemoteNotifications()
注冊遠程通知。
現在,當應用程序收到推送通知時,可能會發生幾種不同的情況。 我會嘗試列出最常見的案例。
本地通知:
如果應用程序位於前台,則應用程序將調用UserNotificationController .userNotificationCenter(_:willPresent:withCompletionHandler:)
。
如果應用程序在后台(運行與否),則在用戶點擊通知之前不會調用任何內容,此時應用程序將打開並調用UserNotificationController .userNotificationCenter(_:didReceive:withCompletionHandler:)
。
遠程通知:
有效載荷的內容將影響發生的事情。 有效載荷有三種情況:a)正常alert
, badge
和sound
選項b)包括content-available
選項(設置為1
或true
)c)包括mutable-content
選項(設置為1
或true
) 。 另外,技術上d)你有content-available
和mutable-content
,但這只會觸發兩種情況。
對於a) alert
, sound
, badge
信息:
這與本地通知相同。
對於b) content-available
== true:
如果應用程序位於前台,則UserNotificationController .userNotificationCenter(_:willPresent:withCompletionHandler:)
。
如果應用程序在后台(運行與否),則調用AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
,而不是UserNotificationController
類中的UserNotificationController
方法。
對於c) mutable-content
== true:
如果您已將UNNotificationServiceExtension
添加到應用程序,它將處理通知並可以修改內容。 無論主應用程序的狀態如何,都會發生這種情況。 如果用戶點擊(可選地修改的)通知,則其被處理為類似於上面的本地通知。
如果沒有UNNotificationServiceExtension
,通知將被視為上面的正常遠程通知。
補充筆記:
使用mutable-content
,必須在有效負載中包含alert
信息,否則系統會將其視為不可變,而不是調用UNNotificationServiceExtension
。 您修改的通知仍必須包含alert
信息,否則將使用原始通知有效負載。 遺憾的是,沒有辦法阻止通知出現在用戶身上。
當使用content-available
,如果用戶上次使用它時強制退出應用程序,系統將不會重新啟動應用程序或調用AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
。 雖然它仍然會顯示任何警報,播放聲音,並按照有效負載中的指示更新徽章。
嘗試讓AppDelegate類實現UNUserNotificationCenterDelegate協議,而不是實現協議的單獨類。
我有一個單獨的代表類,它沒有用。 這就是我的代碼在我工作時的樣子:
import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application
UIApplication.shared.registerForRemoteNotifications()
let center = UNUserNotificationCenter.current()
center.delegate = self //DID NOT WORK WHEN self WAS MyOtherDelegateClass()
center.requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
// Enable or disable features based on authorization.
if granted {
// update application settings
}
}
return true
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent: UNNotification,
withCompletionHandler: @escaping (UNNotificationPresentationOptions)->()) {
withCompletionHandler([.alert, .sound, .badge])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive: UNNotificationResponse,
withCompletionHandler: @escaping ()->()) {
withCompletionHandler()
}
// and so forth for your other AppDelegate stuff
我整整都掙扎了一整天。 有時我收到通知,有時候沒有收到通知,但我永遠無法將userNotificationCenter(_:willPresent:completionHandler:)
回調發送到userNotificationCenter(_:willPresent:completionHandler:)
。
原來有兩個問題。 第一個我仍然有點困惑:我的目標部署版本設置為11.0但我的項目設置為10.0。 將項目更改為11.0是第一步。 我不完全理解這一點但是10.0和11.0之間的通知處理可能有些不同嗎?
第二部分是通知中心代表。 我在文檔中注意到Apple的注釋 : -
重要
在應用程序完成啟動之前,您必須將代理對象分配給UNUserNotificationCenter對象。 例如,在iOS應用程序中,您必須在應用程序委托的應用程序( :willFinishLaunchingWithOptions :)或應用程序( :didFinishLaunchingWithOptions :)方法中分配它。 調用這些方法后分配委托可能會導致您錯過傳入通知。
我一直在設置一個單獨的“通知管理器”類,這也是回調也位於的地方(作為委托協議實現)。 我已將其實例化為我的app委托中的實例var,假設這將在早期創建並且不會導致問題。
我搞亂了實例化等一段時間,但只有當我在我的application(_:didFinishLaunchingWithOptions:)
設置委托application(_:didFinishLaunchingWithOptions:)
方法並在app委托中實現了委托回調時,我設法修復它。
所以我的代碼基本上成了: -
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// You MUST do this HERE and nowhere else!
UNUserNotificationCenter.current().delegate = self
// other stuff
return true
}
extension AppDelegate: UNUserNotificationCenterDelegate {
// These delegate methods MUST live in App Delegate and nowhere else!
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
if let userInfo = notification.request.content.userInfo as? [String : AnyObject] {
}
completionHandler(.alert)
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if let userInfo = response.notification.request.content.userInfo as? [String : AnyObject] {
}
completionHandler()
}
}
也許不設置UNNotificationCategory
的intentIdentifiers
,如果代碼如下:
UNNotificationCategory* expiredCategory = [UNNotificationCategory
categoryWithIdentifier:@"TIMER_EXPIRED"
actions:@[snoozeAction, stopAction]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
它不會調用UNUserNotificationCenter的委托方法,因此您必須設置這樣的intentIdentifiers:
UNNotificationCategory* expiredCategory = [UNNotificationCategory
categoryWithIdentifier:@"TIMER_EXPIRED"
actions:@[snoozeAction, stopAction]
intentIdentifiers:@[@"a",@"b"]
options:UNNotificationCategoryOptionCustomDismissAction];
除了確保您使用AppDelegate
用於UNUserNotificationCenter
委托,並在啟動時在application:didFinishLaunchingWithOptions
方法中設置委托,請確保您還記得導入UserNotifications
和UserNotificationsUI
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.