簡體   English   中英

未調用iOS 10 UNUserNotificationCenterDelegate。 推送通知無效

[英]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)正常alertbadgesound選項b)包括content-available選項(設置為1true )c)包括mutable-content選項(設置為1true ) 。 另外,技術上d)你有content-availablemutable-content ,但這只會觸發兩種情況。

對於a) alertsoundbadge信息:

這與本地通知相同。

對於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()
    }
}

也許不設置UNNotificationCategoryintentIdentifiers ,如果代碼如下:

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方法中設置委托,請確保您還記得導入UserNotificationsUserNotificationsUI

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM