如何在iOS 10中处理用户通知操作

8
所以我可以像这样安排通知;
//iOS 10 Notification
if #available(iOS 10.0, *) {

    var displayDate: String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = DateFormatter.Style.full
        return dateFormatter.string(from: datePicker.date as Date)
    }
    let notif = UNMutableNotificationContent()


    notif.title = "I am a Reminder"
    notif.subtitle = "\(displayDate)"
    notif.body = "Here's the body of the notification"
    notif.sound = UNNotificationSound.default()
    notif.categoryIdentifier = "reminderNotification"

    let today = NSDate()
    let interval = datePicker.date.timeIntervalSince(today as Date)

    let notifTrigger = UNTimeIntervalNotificationTrigger(timeInterval: interval, repeats: false)

    let request = UNNotificationRequest(identifier: "reminderNotif", content: notif, trigger: notifTrigger)

    UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
        if error != nil {
            print(error)
           // completion(Success: false)
        } else {
            //completion(Sucess: true)
        }
        })
}

我已经在appDelegate中请求了权限,并使用通知扩展显示了自定义视图的通知。我还为通知类别添加了通知操作,在appDelegate中也可以看到它们。
//Notifications Actions 

private func configureUserNotifications() {
    if #available(iOS 10.0, *) {

        let tomorrowAction = UNNotificationAction(identifier: "tomorrowReminder", title: "Remind Me Tomorrow", options: [])

        let dismissAction = UNNotificationAction(identifier: "dismissReminder", title: "Dismiss", options: [])


        let category = UNNotificationCategory(identifier: "reminderNotification", actions: [tomorrowAction, dismissAction], intentIdentifiers: [], options: [.customDismissAction])

        UNUserNotificationCenter.current().setNotificationCategories([category])

    } else {
        // Fallback on earlier versions
    }
}

在通知扩展的.plist文件中,我设置了相同的类别。当用户点击操作时,我在通知扩展中使用以下内容来更改文本。

 //Handle Notification Actions And Update Notification Window 


 private func didReceive(_ response: UNNotificationResponse, completionHandler done: (UNNotificationContentExtensionResponseOption) -> Void) {

    if response.actionIdentifier == "tomorrowReminder" {
        print("Tomrrow Button Pressed")
        subLabel.text = "Reminder For Tomorrow"
        subLabel.textColor = UIColor.blue
        done(.dismissAndForwardAction)
    }

    if response.actionIdentifier == "dismissReminder" {
        print("Dismiss Button Pressed")
        done(.dismiss)

    } else {
        print("Else response")
        done(.dismissAndForwardAction)
    }

}

然而,文本没有改变,也没有调用任何语句;

在appDelegate中,我有以下内容;

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().delegate = self
        configureUserNotifications()

    }
}

extension AppDelegate: UNUserNotificationCenterDelegate {

@available(iOS 10.0, *)
private func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert, .sound])
}

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

    print("Recieved Action For \(response.actionIdentifier)")

    if response.actionIdentifier == "tomorrowReminder" {
        print("Tomorrow Reminder")


        //Set new reminder for tomorrow using the notification content title



        completionHandler()
    }

    if response.actionIdentifier == "dismissReminder" {
        print("Dismiss Reminder...")
        completionHandler()
    }
}

}

这两个函数都没有在appDelegate中被调用。我不确定更新扩展视图的问题是否与应用程序委托有关。我认为不是,我已经按照苹果的WWDC视频以及其他教程和文档API进行了操作,但仍无法解决以下问题:

  • 通知扩展文本标签为什么没有更新?
  • 为什么appDelegate中的函数没有被调用?
  • 如何在应用程序委托中使用通知内容来执行操作?

PS:我花了过去几周的时间进行研究和尝试,看起来非常简单,但我不确定自己漏掉了什么。我知道我不是唯一遇到这些问题的人。

1个回答

5

我还没有检查完您的所有代码,但至少以下这些函数头需要进行更改:

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

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

func didReceive(_ response: UNNotificationResponse,
                completionHandler done: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {

简单的规则: 移除private,添加@escaping

您可能会从Xcode中收到错误建议,但是如果将它们设置为private,则不会生成Objective-C入口点。iOS运行时在内部使用Objective-C选择器,因此无法找到您的方法,因此它们不会被执行。


@escaping 表示什么意思并起到什么作用? - mfaani
哇,谢谢你!你知道我怎么在应用程序委托中使用 notification.request.content.title 来安排新的通知吗?例如,我正在尝试安排一个提醒,并有一个动作来提醒明天再次提醒。 - A.Roe
没关系,我所需要做的就是使用 response.notification.request.content.title - A.Roe
1
@Honey,“@escaping”的意思是“这个闭包可能会在以后执行”。编译器可以轻松优化非逃逸闭包,这些闭包通常用于mapfilter等操作。Swift 3已经将其设置为默认值。所有完成处理程序都在某个任务完成后执行--稍后,因此我们需要在Swift 3中为所有完成处理程序注释@escaping - OOPer
@OOPer,有没有关于@escaping的文档?我找不到。顺便说一下,我通常很难找到适当的Swift文档... - mfaani
1
@Honey,这里有一篇很好的文章在SO(https://dev59.com/5lkT5IYBdhLWcg3wG70_#39063972)。Swift.org的文章不太友好,但对于那些使用Swift 2&3的人来说是必看的。苹果的文档正在改进,最新的参考资料(不幸的是,并非全部都是最新的)和Xcode发布说明(https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html)给我们提供了一些信息。 - OOPer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接