设置多天后本地通知不会触发

Local notification not firing when multiple days set

我正在尝试为一周中的特定几天创建一个重复的本地通知,但在那些日子的同一时间。

该应用将允许用户为不同的列表项设置多个本地通知;例如:

Item 1: Sunday, Monday, Tuesday - 9:00am
Item 2: Monday, Wednesday - 6:00pm
Item 3: Monday, Tuesday - 9:00am
Item 4: Friday - 12:00pm

因此可以在同一天或同一时间设置多个通知。

目前,当我为单日设置日程表(示例项目 #4)时,它工作正常。弹出通知。

当我安排超过一天的时间时,通知似乎没有注册,或者没有通过。

我一直在搜索代码,看看我是否能看到哪里,但我一辈子都看不到它不会被设置的地方。

这是一个基本代码,但它确实演示了它是如何设置的,以及它是如何不工作的:

import SwiftUI
import UserNotifications

struct AlarmModel {
 let id = UUID().uuidString
 let title: String
 let subtitle: String
 let body: String
 let days: [Int]
 let hour: Int
 let minute: Int
}

struct ContentView: View {
 @State var array = [1, 2, 3, 4, 5, 6, 7]
 @State private var selectedDays: [Int] = []
 @State private var currentTime: Date = Date()
 let nc = NotificationManager()

 var body: some View {
  Form {
   Section {
    HStack(spacing: 10) {
     ForEach(array, id: \.self) { day in
      Text("\(day)")
       .bold()
       .frame(maxWidth: .infinity, maxHeight: .infinity)
       .foregroundColor(.white)
       .background(
        Circle()
         .foregroundColor(
          selectedDays.contains(day) ?
           .accentColor : .gray
         )
       )
       .onTapGesture { checkActiveDays(day) }
     }
    }
    .frame(maxWidth: .infinity, minHeight: 50)
   } header: {
    Text("Days of the week - 1=Sunday, 7=Saturday")
   } footer: {
    Text("1 = SUN / 2 = MON / 3 = TUES / 4 = WED / 5 = THURS / 6 = FRI / 7 = SAT")
   }

   Section {
    DatePicker("Alert time", selection: $currentTime, displayedComponents: .hourAndMinute)
   } header: {
    Text("Select alert time")
   }

   Section {
    Button {
     saveNotification()
    } label: {
     Text("Set alert")
    }

   }
  }
 }
 private func checkActiveDays(_ index: Int) {
  if( selectedDays.contains(index) ) {
   selectedDays.remove(at: selectedDays.firstIndex(of: index)!)
  } else {
   selectedDays.append(index)
  }
 }

 private func saveNotification() {
  let alarm = AlarmModel(
   title: "Test alert title",
   subtitle: "Test subtitle",
   body: "Test body text",
   days: selectedDays,
   hour: Calendar.current.component(.hour, from: currentTime),
   minute:  Calendar.current.component(.minute, from: currentTime)
  )

  // -- add it
  nc.addNotification(alarm: alarm)
 }
}


final class NotificationManager {
 var notifications: [Notification] = []
 let nc = UNUserNotificationCenter.current()

 init() {
  nc.requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
   if granted == true && error == nil {
    print("Notifications permitted")
   } else {
    print("Notifications not permitted")
   }
  }
 }

 private func createNotification(id: String, weekDay: Int, hour: Int, minute: Int, content: UNNotificationContent) {

  var dateComponents = DateComponents()
  dateComponents.weekday = weekDay
  dateComponents.hour = hour
  dateComponents.minute = minute

  let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
  let request = UNNotificationRequest(identifier: id, content: content, trigger: trigger)

  nc.add(request) { error in
   if let error = error { print("Error \(error.localizedDescription)") }
  }
 }

 func addNotification(alarm: AlarmModel) {
  nc.removePendingNotificationRequests(withIdentifiers: [alarm.id])

  let content = UNMutableNotificationContent()
  content.title = alarm.title
  content.subtitle = alarm.subtitle
  content.body = alarm.body
  content.sound = .default

  if(alarm.days.count > 0) {
   for day in alarm.days {
    createNotification(
     id: alarm.id,
     weekDay: day,
     hour: alarm.hour,
     minute: alarm.minute,
     content: content
    )
   }
  }
 }
}

循环中每个通知的 id 必须是唯一的。

您对所有通知使用相同的 id。最新的覆盖以前的。

在末尾添加 id String 的独特内容,例如索引或其他 UUIDday 描述。