为什么本地通知不触发UNCalendarNotificationTrigger



本地通知应该在2021年9月25日发射。下面是fire time

的打印对象

year: 2021 month: 9 day: 26 isLeapMonth: false

  • 年份:2021
  • 月:9
  • day: 25
  • isLeapMonth: false
let content = UNMutableNotificationContent()
content.title = "Test title"
content.body = "sample test body"
var trigger:UNCalendarNotificationTrigger
let n = 1
let nextTriggerDate = Calendar.current.date(byAdding: .day, value: n, to: Date())!
let comps = Calendar.current.dateComponents([.year, .month, .day], from: nextTriggerDate)
trigger = UNCalendarNotificationTrigger(dateMatching: comps, repeats: false)
content.subtitle = "Sub title-Date-NonRepeat"
let request = UNNotificationRequest(identifier: "test.my.example", content: content, trigger: trigger)    
UNUserNotificationCenter.current().add(request) { Error in                        
if let err = Error {
print("Notification Error:(String(describing: err))")
}
}

我再次在Date中添加了time,代码修改如下

var comps = Calendar.current.dateComponents([.year, .month, .day], from: nextTriggerDate)
comps.day = 25
comps.hour = 12
comps.minute = 17
comps.second = 10

这是comps变量的PO

var comps = Calendar.current.dateComponents([。年,月,日],来自:nextTriggerDate)比较。一天= 25比较。小时= 12比较。分钟= 17分钟比较。秒= 10

我给了date来查看它是否触发我给了date和time来查看它是否触发我在主线程中做了所有的事情,它没有工作

谁能让我明白我做错了什么

您可能没有首先请求权限

import SwiftUI
//struct and class should start with an uppercase
struct NotificationView: View {
//Central location for Notification code including the delegate
// A call to the notificationManager just like the one below has to be included in
// application(_:willFinishLaunchingWithOptions:) or
// application(_:didFinishLaunchingWithOptions:)
//https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate
//https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-an-appdelegate-to-a-swiftui-app
let notificationManager: NotificationManager = NotificationManager.shared
var body: some View {
VStack {
VStack {
Button("Request Permission") {
//Call a func here don't define it
notificationManager.requestAuthorization()
}
.frame(width: 200, height: 60, alignment: .center)
.foregroundColor(.black)
.background(Color.blue)
.cornerRadius(10.0)
.padding()
Button("Add custom trigger") {
let apiDate = DateComponents(year: 2021, month: 11, day: 10, hour: 16, minute: 0, second: 0)
notificationManager.scheduleBasedOnDaysBeforeDate(title: "test", body: "test", baseDate: Calendar.current.date(from: apiDate)!, xDaysBefore: 10, count: 12, identifier: UUID().uuidString)
}
.padding()
Button("Print Notifications") {
//Reusable method
self.notificationManager.printNotifications()
}
Button("Print Delivered Notifications") {
//Reusable method
self.notificationManager.printDeliveredNotifications()
}
.foregroundColor(.blue)
.padding()
Button("Delete Notifications") {
//Reusable method
self.notificationManager.deleteNotifications()
}
.foregroundColor(.blue)
.padding()
}
}
}
}
class NotificationManager: NSObject, UNUserNotificationCenterDelegate{
//Singleton is requierd because of delegate
static let shared: NotificationManager = NotificationManager()
let notificationCenter = UNUserNotificationCenter.current()

private override init(){
super.init()
//This assigns the delegate
notificationCenter.delegate = self
}
func scheduleUNCalendarNotificationTrigger(title: String, body: String, dateComponents: DateComponents, identifier: String, repeats: Bool = false){
print(#function)
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.sound = .default

let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: repeats)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
notificationCenter.add(request) { (error) in
if error != nil {
print(error!)
}
}
}
func scheduleUNTimeIntervalNotificationTrigger(title: String, body: String, timeInterval: TimeInterval, identifier: String, repeats: Bool = false){
print(#function)
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.sound = .default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval, repeats: repeats)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
notificationCenter.add(request) { (error) in
if error != nil {
print(error!)
}
}
}
///Schedules `count` number of monthly notifications that occur `xDaysBefore` the `baseDate`
func scheduleBasedOnDaysBeforeDate(title: String, body: String, baseDate: Date, xDaysBefore: Int, count: Int, identifier: String){
print(#function)
var nextBaseDate: Date = baseDate

for n in 1...count{

guard let triggerDate: Date = Calendar.current.date(byAdding: .day, value: -xDaysBefore, to: nextBaseDate) else{
return
}
let components: DateComponents = Calendar.current.dateComponents([.month,.day, .hour,.minute,.second], from: triggerDate)
let id = identifier.appending(" (n)")
scheduleUNCalendarNotificationTrigger(title: title, body: body, dateComponents: components, identifier: id)
//OR if you want specific seconds 
//let interval = Calendar.current.dateComponents([.second], from: Date(), to: triggerDate).second ?? 1

//scheduleUNTimeIntervalNotificationTrigger(title: title, body: body, timeInterval: TimeInterval(interval), identifier: id)

let next = Calendar.current.date(byAdding: .month, value: 1, to: nextBaseDate)

if next != nil{

nextBaseDate = next!
}else{
print("next == nil")
return
}
}
self.printNotifications()

}
func requestAuthorization() {
print(#function)
notificationCenter.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
print("Access Granted!")
} else {
print("Access Not Granted")
}
}
}

func deleteNotifications(){
print(#function)
notificationCenter.removeAllPendingNotificationRequests()
}

///Prints to console schduled notifications
func printNotifications(){
print(#function)
notificationCenter.getPendingNotificationRequests { request in
print("UNTimeIntervalNotificationTrigger Pending Notification")
for req in request{
if req.trigger is UNTimeIntervalNotificationTrigger{
print((req.trigger as! UNTimeIntervalNotificationTrigger).nextTriggerDate()?.description ?? "invalid next trigger date")
}
}
print("UNCalendarNotificationTrigger Pending Notification")
for req in request{
if req.trigger is UNCalendarNotificationTrigger{
print((req.trigger as! UNCalendarNotificationTrigger).nextTriggerDate()?.description ?? "invalid next trigger date")
}
}
}
}
///Prints to console delivered notifications
func printDeliveredNotifications(){
print(#function)
notificationCenter.getDeliveredNotifications { request in
for req in request{
print(req)
}
}
}
//MARK: UNUserNotificationCenterDelegate
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

completionHandler(.banner)
}
}
struct NotificationView_Previews: PreviewProvider {
static var previews: some View {
NotificationView()
}
}

运行此代码。点击"请求权限"。然后点击"添加自定义触发器"当您单击"print">

时,您应该会在控制台中看到通知。

我已经看了你的代码,很明显你正确地添加了日历触发器,并且你在其中一个评论中提到,你在添加时也获得了必要的许可。

对我来说,这感觉像是某种日期时间问题。检查datetime到datetime组件的转换是否正确。

如果你在模拟器上测试,当你来回改变系统中的日期时,事情会变得很疯狂。

我建议你用真正的设备测试一下。

这是你获得许可的方式

UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.announcement,.sound]) { [self]
(granted, error) in
if granted {
print("granted")
} else {
print("denied or error")
}
}

您可以使用下面的代码查询可用通知列表,以确定它是否在预期的日期时间正确安排。

var text:NSMutableAttributedString? = NSMutableAttributedString(string: "List of notification requests and it's timen")
UNUserNotificationCenter.current().getPendingNotificationRequests() { [weak self] requests in
DispatchQueue.main.async {
for request in requests {
guard let trigger = request.trigger as? UNCalendarNotificationTrigger else { return }
text?.append(NSAttributedString(string: "nTrigger Date:(trigger.nextTriggerDate()?.description) nDateTime Component:(trigger.dateComponents.description)n"))
}
print(text)
}

Update (Credit(lorem ipsum) for the below is from the answer in the question)

func getFireDatetime(apiDate: Date, numberOfDaysBeforeApiDate: Int,repeat:Bool) -> DateComponents? {
if let fireDate: Date = apiDate.dateByAdding(days: -numberOfDaysBeforeApiDate) {
if repeat {
return Calendar.current.dateComponents([.day, .hour, .minute, .second], from: fireDate)
}
return Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: fireDate)
}
return nil
}

调用getFireDatetime方法,这应该解决你所有的问题,我猜

p。S

  • Date()它给你的时间回到通用时间,而Datetime组件将给出Datetime与您的设备当前日历设置。

  • 当您使用Datetime组件时,应该自动处理时区更改和夏令时

相关内容

  • 没有找到相关文章

最新更新