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
}
Я могу запланировать уведомления и получать локальные уведомления в нужное время. НО: мои методы делегатов, которые я использовал в соответствии с учебником, никогда не выполняются, однако 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")
}
}
Не было отменено reReceiveLocalNotification? Как заставить эти методы называть?
UPDATE:
Я обновил свой код с некоторыми предложениями здесь, а именно:
- Я добавил присвоение UNUserNotificationCenter.delegate к applicationDidFinishLaunchingWithOptions.
- Я также попытался переместить эти методы (методы делегатов) из расширения в класс NotificationsController.swift и установить этот класс как UNUserNotificationCenterDelegate. Не работал и для меня.
Ответы
Ответ 1
Идентификатор запроса не является категорией уведомлений.
Просто добавьте эту строку:
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()
}
}
Ответ 2
Использовать метод делегата belwo для Swift 2.3:
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)
Ответ 3
Убедитесь, что ваш 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
Я нашел ответ для этого. Ниже метода делегата вызывается при запуске приложения на Xcode 8 с Swift 2.3 и минимальной целью развертывания как iOS 9.3.
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)
В быстрой версии 3.0 используйте
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void)
Ссылка: https://developer.apple.com/reference/usernotifications/unusernotificationcenterdelegate/1649501-usernotificationcenter
Ответ 5
В соответствии с UNUserNotificationCenterDelegate docs:
Внимание!
Вы должны назначить объект-делегат в UNUserNotificationCenter объект не позднее, чем ваше приложение завершит запуск. Например, в iOS, вы должны назначить его в приложенииWillFinishLaunching (:) или applicationDidFinishLaunching (:).
Таким образом, возможно, слишком поздно установить делегата Центра уведомлений.
Ответ 6
Для 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()
}
Ответ 7
Вы используете неправильные сигнатуры функций
Правильными сигнатурами функций в 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
}
Ответ 8
Документы говорят, чтобы установить делегат в 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])
}
Ответ 9
Убедитесь, что только ваш AppDelegate установлен в качестве делегата UNUserNotificationCenter.
Ты используешь...
UNUserNotificationCenter.current().delegate = self
... больше чем единожды? Я пытался перехватить уведомления с разными результатами во всех моих контроллерах представления, изменив делегат в каждом и заставив каждого использовать эту функцию:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
// code
}
Проблема для меня заключалась в том, что я еще не реализовал их функциональность, и поэтому оригинальная функция userNotificationCenter "didReceive" в моем AppDelegate не вызывалась. Это может быть причиной того, что вам не звонят.