UNUserNotificationCenter did receive response with completion handler is never called iOS10, swift 2.3

怎甘沉沦 提交于 2019-11-28 17:00:02
livsik

Request identifier is not the notification category.

Just add this line:

content.categoryIdentifier = identifier

Update: Just made a simple app. Everything seems to working fine:

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    UNUserNotificationCenter.current().delegate = self

    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
        if granted {
            self.registerCategory()
            self.scheduleNotification(event: "test", interval: 3)
            self.scheduleNotification(event: "test2", interval: 5)
        }
    }

    return true
}

func registerCategory() -> Void{

    let callNow = UNNotificationAction(identifier: "call", title: "Call now", options: [])
    let clear = UNNotificationAction(identifier: "clear", title: "Clear", options: [])
    let category : UNNotificationCategory = UNNotificationCategory.init(identifier: "CALLINNOTIFICATION", actions: [callNow, clear], intentIdentifiers: [], options: [])

    let center = UNUserNotificationCenter.current()
    center.setNotificationCategories([category])

}

func scheduleNotification (event : String, interval: TimeInterval) {
    let content = UNMutableNotificationContent()

    content.title = event
    content.body = "body"
    content.categoryIdentifier = "CALLINNOTIFICATION"
    let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval, repeats: false)
    let identifier = "id_"+event
    let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)

    let center = UNUserNotificationCenter.current()
        center.add(request, withCompletionHandler: { (error) in
    })

}

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    print("didReceive")
    completionHandler()
}

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    print("willPresent")
    completionHandler([.badge, .alert, .sound])
}

}

Update 2: Rewritten in Swift 2.3

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

var window: UIWindow?

func applicationDidFinishLaunching(application: UIApplication) {
    UNUserNotificationCenter.currentNotificationCenter().delegate = self
    UNUserNotificationCenter.currentNotificationCenter().requestAuthorizationWithOptions([.Badge, .Sound, .Alert]) { (granted, error) in
        if granted {
            self.registerCategory()
            self.scheduleNotification("test", interval: 3)
            self.scheduleNotification("test2", interval: 5)
        }
    }
}


func registerCategory() -> Void{

    let callNow = UNNotificationAction(identifier: "call", title: "Call now", options: [])
    let clear = UNNotificationAction(identifier: "clear", title: "Clear", options: [])
    let category : UNNotificationCategory = UNNotificationCategory.init(identifier: "CALLINNOTIFICATION", actions: [callNow, clear], intentIdentifiers: [], options: [])

    let center = UNUserNotificationCenter.currentNotificationCenter()
    center.setNotificationCategories([category])

}

func scheduleNotification(event : String, interval: NSTimeInterval) {
    let content = UNMutableNotificationContent()

    content.title = event
    content.body = "body"
    content.categoryIdentifier = "CALLINNOTIFICATION"
    let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval, repeats: false)
    let identifier = "id_"+event
    let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)

    let center = UNUserNotificationCenter.currentNotificationCenter()
    center.addNotificationRequest(request) { (error) in

    }
}

func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {

    print("willPresent")
    completionHandler([.Badge, .Alert, .Sound])
}

func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {

    print("didReceive")
    completionHandler()
}

}

Use belwo delegate method for Swift 2.3:

func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)

Make sure your AppDelegate implementing UNUserNotificationCenterDelegate protocol.

For Swift

let center = UNUserNotificationCenter.current()
center.delegate = self

For Objective-c

//set delegate to self
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];

Assigning delegate to self will trigger following methods.

// App in foreground
    private func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
      print("willPresent")
      }
//On Action click
     private func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
      print("didReceive")
      }

I have found the answer for this. Below delegate method is called while running app on Xcode 8 with Swift 2.3 and minimum deployment target as iOS 9.3.

func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)

In swift 3.0 Use,

func userNotificationCenter(_ center: UNUserNotificationCenter, 
                      didReceive response: UNNotificationResponse, 
           withCompletionHandler completionHandler: @escaping () -> Void)

Reference: https://developer.apple.com/reference/usernotifications/unusernotificationcenterdelegate/1649501-usernotificationcenter

According to the UNUserNotificationCenterDelegate docs:

Important

You must assign your delegate object to the UNUserNotificationCenter object no later before your app finishes launching. For example, in an iOS app, you must assign it in the applicationWillFinishLaunching(:) or applicationDidFinishLaunching(:) method.

So, it could be an issue of setting the Notification Centre delegate too late.

For Swift 3.0

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

    print("** willPresent")
    completionHandler([.badge, .alert, .sound])
}

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    print("** didReceive")
    completionHandler()
}

You are using incorrect function signatures

The correct function signatures in swift are:

func userNotificationCenter(UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {

//your code here

}

and

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {

//your code here

}

Check to make sure that only your AppDelegate is set as the UNUserNotificationCenter Delegate.

Are you using...

UNUserNotificationCenter.current().delegate = self

... more than once? I was trying to catch notifications with different outcomes in all of my view controllers by changing the delegate in each one and having each use this function:

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
   // code
}

The issue for me was that I hadn't implemented their functionality yet, and so the original userNotificationCenter function "didReceive" in my AppDelegate wasn't being called. This may be why yours isn't getting called.

The docs says to set the delegate in applicationWillFinishLaunching(:) or applicationDidFinishLaunching(:). So include the following code in AppDelegate:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
   UNUserNotificationCenter.current().delegate = self
}

After this delegate is being set, the following willPresent function will be called.

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
   print("willPresent")
   completionHandler([.alert, .sound])
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!