Xcode swiftui中的重复报警通知

Xcode swiftui中的重复报警通知,xcode,swiftui,xcode12,Xcode,Swiftui,Xcode12,我已经创建了一段代码,可以在下午3点发送本地通知,用户可以使用切换开关进行切换。我使用AppStorage包装器来记住它所处的状态。代码一直工作到我打开和关闭开关(模拟用户是否多次切换)以及我切换开关的次数,相同的次数作为通知出现(即,我切换5次,我一次收到5个通知)。这是密码 struct trial: View { @AppStorage("3") var three = false func first

我已经创建了一段代码,可以在下午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时安排一个新的通知

这段代码意味着每次调用此方法时都会安排一个新的通知

//选择一个随机标识符
let request=UNNotificationRequest(标识符:UUID().uuidString,内容:content,触发器:trigger)
//添加我们的通知请求
UNUserNotificationCenter.current().add(请求)
不完全确定所需的逻辑是什么,但您可以通过更新现有通知或清除旧通知并添加新通知来解决此问题。与其为每个通知创建一个新的UUID,最好是有一个ID约定或存储它,以便可以访问或删除它

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


@AppStorage(“notification_id”)var notificationID=nil//我不知道这是字符串还是nil,但希望它能指引您正确的方向。
//然后在创建请求时。
让id=通知id??UUID().UUIString
let request=UNNotificationRequest(标识符:id,内容:content,触发器:trigger)
notificationID=id
当他们切换到另一个方向时,需要另一种方法来取消计划。您只需检查该id是否存在


如果let id=notificationID{
UnuseNotificationCenter.current()。移除挂起的NotificationRequests(带标识符:[id])
//或
UnuseNotificationCenter.current()删除所有相关的NotificationRequests()
}

我希望用户只需决定是否需要通知。我有点明白你想说什么,但我不知道如何给这个警报一个id。我更新了我的答案,上面有一些更具体的内容。如果您对如何组合有任何更具体的问题,请告诉我。我在使用新func时遇到了一些问题。我创建了一个名为turnoff的新func,但它给了我一个错误“条件绑定的初始值设定项必须具有可选类型,而不是'String'”。好的,听起来ID不是可选的。因此,与上面显示的展开不同,只需继续使用“关闭”方法将通知与存储的“我要”或“全部删除”,无需展开任何内容。我尝试了您的建议,但仍然无法工作。通知仍然会被触发很多次