swiftui 重复报警通知

repeated alarm notifications in swiftui

我创建了一段代码,用于在下午 3 点发送本地通知,用户可以使用切换开关来切换它。我使用 AppStorage 包装器来记住它所处的状态。代码一直有效,直到我打开和关闭开关(模拟用户是否多次切换)以及我切换开关的次数,相同的数字作为通知(即我切换 5 次,一次收到 5 条通知)。这是代码


struct trial: View {
    
    
    
    @AppStorage("3") var three = false
    
    
    func firstNotify() {
        
        let content = UNMutableNotificationContent()
        content.title = "It is 3pm"
        content.subtitle = "Read the Prime Hour"
        content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "notifysound.wav"))
        
      //  content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "notifysound"))
        
        
        var dateComponents = DateComponents()
        dateComponents.hour = 15
        dateComponents.minute = 00
        dateComponents.second = 00

        
        
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
        
        // choose a random identifier
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
        // add our notification request
        UNUserNotificationCenter.current().add(request)
        
        
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
            if success {
                print("All set!")
            } else if let error = error {
                print(error.localizedDescription)
            }
        }
        
    }
    
    
    @State private var name: String = "Tim"
    
    
    var body: some View {
        VStack {
            
            Toggle(isOn: $three) {
                Text("3 pm")
            }
            .padding(.horizontal)
            .onChange(of: three) { newValue in
                if newValue {
                    firstNotify()
                }
            }
            
   
        }
    }
}

struct trial_Previews: PreviewProvider {
    static var previews: some View {
        trial()
    }
}


我认为正在发生的事情是 func 没有读取开关是打开还是关闭,而是在每次打开开关时添加一个通知。有人知道解决办法吗???

切换实际上只是在每次将值更改为 true 时安排新通知。

这段代码的意思是每次调用这个方法都会安排一个新的通知。

     // choose a random identifier
    let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
    // add our notification request
    UNUserNotificationCenter.current().add(request)

不完全确定所需的逻辑是什么,但您可以通过更新现有通知或清除旧通知并添加新通知来解决此问题。与其为每个通知创建一个新的 UUID,最好有一个 ID 约定或以其他方式存储它以便可以访问或删除它。

您可以存储而不是切换值:


@AppStorage("notification_id") var notificationID = nil // I don't know if this can be a string or nil, but hopefully it leads you in the right direction.

// Then when creating the request.

let id = notificationID ?? UUID().uuidString
let request = UNNotificationRequest(identifier: id, content: content, trigger: trigger)
notificationID = id


当他们切换另一个方向时,需要有另一种方法来取消计划。您可以简单地检查该 ID 是否存在。


if let id = notificationID {
    UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers identifiers: [id])

    // OR

    UNUserNotificationCenter.current()removeAllPendingNotificationRequests()
}