web-dev-qa-db-ja.com

UNUserNotificationCenterは、iOS10と呼ばれることのない完了ハンドラーで応答を受信しました、Swift 2.3

次のように、iOS10で新しい通知をスケジュールしています。

func scheduleNotification (event : Meeting, todaysBadgeCounter: Int) {

    if #available(iOS 10.0, *) {

        let minutesBefore = 10
        //interval in seconds from current point in time to notification
        let interval : NSTimeInterval = NSTimeInterval(secondsFromNowTo(event.startTime.dateByAddingTimeInterval(-minutesBefore * 60)))

        //only schedule in the future
        if(interval > 0){


            let category = NotificationsController.notificationCategory

            let center = NotificationsController.notificationCenter
            center.setNotificationCategories([category])
            let content = UNMutableNotificationContent()

            content.title = NSString.localizedUserNotificationStringForKey(event.title, arguments: nil)
            if(minutesBefore <= 1){
                content.body = NSString.localizedUserNotificationStringForKey("IOS10: Your \(event.title) is about to start", arguments: nil)
            }else{
                content.body = NSString.localizedUserNotificationStringForKey("IOS10: You have \(event.title) in \(Int(minutesBefore)) minutes", arguments: nil)

            }
            content.sound = UNNotificationSound.defaultSound()

            let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval, repeats: false)
            let identifier = NSString.localizedUserNotificationStringForKey("sampleRequest\(event.UUID)", arguments: nil)
            let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)

            //setting the delegate
            center.delegate = self

            center.addNotificationRequest(request, withCompletionHandler: { (error) in
                // handle the error if needed
                log.error(error?.localizedDescription)
                print("SCHEDULING >=iOS10:", event.title, ", interval:", interval)
            })
        }


//return category
@available(iOS 10.0, *)
class var notificationCategory : UNNotificationCategory {
    struct Static {
        static let callNow = UNNotificationAction(identifier: NotificationActions.callNow.rawValue, title: "Call now", options: [])
        static let clear = UNNotificationAction(identifier: NotificationActions.clear.rawValue, title: "Clear", options: [])
        static let category : UNNotificationCategory = UNNotificationCategory.init(identifier: "CALLINNOTIFICATION", actions: [callNow, clear], intentIdentifiers: [], options: [])

    }
    return Static.category
}

通知をスケジュールし、適切なタイミングでローカル通知を受信できます。 BUT:チュートリアルに従って使用したデリゲートメソッドは実行されませんが、通知をタップするたびにdidReceiveLocalNotificationが実行されます。

extension NotificationsController: UNUserNotificationCenterDelegate {

@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {

    print("IOS10 delivered")

    // Response has actionIdentifier, userText, Notification (which has Request, which has Trigger and Content)
    switch response.actionIdentifier {
    case NotificationActions.NotifyBefore.rawValue:
        print("notify")
        break

    case NotificationActions.callNow.rawValue:
        print("callNow")
        break
    case NotificationActions.clear.rawValue:
        print("clear")
    default: break
    }
}

@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {

        // Delivers a notification to an app running in the foreground.
        print("IOS10 delivered 2222")

    }
}

DidReceiveLocalNotificationは廃止されませんでしたか?これらのメソッドを呼び出す方法は?

更新:

私はここからいくつかの提案でコードを更新しました:すなわち:

  1. UNUserNotificationCenter.delegateの割り当てをapplicationDidFinishLaunchingWithOptionsに追加しました。
  2. また、これらのメソッド(デリゲートメソッド)をNotificationsController.Swiftクラスの拡張から移動し、このクラスをUNUserNotificationCenterDelegateとして設定しようとしました。私にとってもうまくいかなかった。
36
Async-

リクエスト識別子は通知カテゴリではありません。

次の行を追加してください:

content.categoryIdentifier = identifier

更新:単純なアプリを作成しました。すべてがうまく機能しているようです:

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])
}

}

更新2: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()
}

}
18
livsik

Swift 2.3にbelwoデリゲートメソッドを使用します。

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

これに対する答えを見つけました。以下のデリゲートメソッドは、Swift 2.3およびiOS 9.3としての最小展開ターゲットでXcode 8でアプリを実行しているときに呼び出されます。

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

Swift 3.0 Useでは、

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

リファレンス: https://developer.Apple.com/reference/usernotifications/unusernotificationcenterdelegate/1649501-usernotificationcenter

4
user1140780

AppDelegateがUNUserNotificationCenterDelegateプロトコルを実装していることを確認してください。

Swiftの場合

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

Objective-cの場合

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

Selfにデリゲートを割り当てると、次のメソッドがトリガーされます。

// 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")
      }
4
Avijit Nagare

NUserNotificationCenterDelegate docs :によると

重要

アプリの起動が完了する前に、デリゲートオブジェクトをUNUserNotificationCenterオブジェクトに割り当てる必要があります。たとえば、iOSアプリでは、applicationWillFinishLaunching(:)またはapplicationDidFinishLaunching(:)メソッドで割り当てる必要があります。

そのため、通知センターのデリゲートの設定が遅すぎる可能性があります。

3
spassas

For Swift 3.

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()
}
2
Matias Tebele

間違った関数シグネチャを使用しています

Swiftの正しい関数シグネチャは次のとおりです。

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

//your code here

}

そして

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

//your code here

}
1
crow

AppDelegateのみがUNUserNotificationCenterデリゲートとして設定されていることを確認してください。

使っていますか...

UNUserNotificationCenter.current().delegate = self

... 一回以上?私はすべてのView Controllerでそれぞれのデリゲートを変更し、それぞれにこの機能を使用させることで、異なる結果の通知をキャッチしようとしました:

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

私にとっての問題は、それらの機能をまだ実装していないため、AppDelegateの元のuserNotificationCenter関数「didReceive」が呼び出されなかったことです。これがあなたの電話が呼ばれない理由かもしれません。

1
Caleb Hensley

ドキュメントでは、applicationWillFinishLaunching(:)またはapplicationDidFinishLaunching(:)でデリゲートを設定するように指示されています。したがって、AppDelegateに次のコードを含めます。

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

このデリゲートが設定された後、次のwillPresent関数が呼び出されます。

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