Установка времени из набора даты для напоминания

#swift #timer #notifications #intervals #reminders

#swift #таймер #уведомления #интервалы #напоминания

Вопрос:

Пример (я пытаюсь создать что-то вроде этого. Теперь вы можете видеть, здесь вы можете выбрать время и интервал)

Я создал напоминание, в котором пользователь может выбирать, как часто получать уведомления (каждые 2 дня, каждые 3 дня и т.д.), Но я также хочу, чтобы пользователь мог выбирать время. Я знаю, как создать напоминание, которое будет отправлять уведомления в выбранное время, но я должен использовать UNCalendarNotificationTrigger , и проблема в том, что я использую UNTimeIntervalNotificationTrigger . Спасибо

 @IBOutlet weak var picker: UIPickerView!
    
@IBOutlet weak var timePicker: UIDatePicker!

 @IBAction func setReminderBtnTapped(_ sender: Any) {
        
        let content = UNMutableNotificationContent()
        content.title = "Test"
        content.body = "Blablabla"
        content.sound = .default
        

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval((picker.selectedRow(inComponent: 1) 1)*(24*3600)), repeats: true)
        let request = UNNotificationRequest(identifier: "blabla.reminder", content: content, trigger: trigger)
        
   
        UNUserNotificationCenter.current().add(request) { (error) in
            if let error = error {
                print("error")
            }
        }
        print("Notification added")
        
    }
 

Ответ №1:

попробуйте этот код:

 private func setLocalNotification(hour: Int, minute: Int, completionHandler: @escaping (Bool) -> Void) {
   
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options: [.alert, .badge, .sound]) { [weak self] (granted, error) in
        guard let self = self else {
            return
        }
        
        let center = UNUserNotificationCenter.current()
        center.removeAllPendingNotificationRequests()
        
        guard error == nil else {
            completionHandler(false)
            return
        }
        
        if granted {
            
            let content = UNMutableNotificationContent()
            content.title = "title"
            content.sound = UNNotificationSound.default
            content.badge = 1
            
            var dateComponents = DateComponents()
            dateComponents.hour = hour
            dateComponents.minute = minute
            let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
            
            let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
            center.add(request)
            
            completionHandler(true)
            return
        }
        
        completionHandler(false)
    }
}
 

и вы можете вызвать, получив дату из DatePicker следующим образом:

 let date = self.timepPicker.date
let calendar = Calendar.current
   let hour = calendar.component(.hour, from: date) // get hour
let minutes = calendar.component(.minute, from: date) // get minute

self.setLocalNotification(hour: hour, minute: minutes) { [weak self] isSet in
    guard let self = self else {
        return
    }

    if !isSet {
        let center = UNUserNotificationCenter.current()
        center.removeAllPendingNotificationRequests() // remove previus notification
    }
}
 

обновляйте ответ для
повторения X раз в каждый n день:

создать расширение из date для создания простых компонентов date getDateComponents:

 extension Date {
    public func getDateComponents() -> DateComponents {
        let dateComponents = Calendar.current.dateComponents([.hour, .minute, .second, .day], from: self)
        
        return dateComponents
    }
}
 

и обновите функцию setLocalNotification:

 private func setLocalNotification(repeatCount: Int, jumpNextDay: Int, hour: Int, minute: Int) {
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
            let center = UNUserNotificationCenter.current()
            center.removeAllPendingNotificationRequests()
            
            guard error == nil else {
                return
            }
            
            if granted {
                
                let content = UNMutableNotificationContent()
                content.title = "title"
                content.sound = UNNotificationSound.default
                content.badge = 1
                
                // create date from hour and minute based on current
                let firstDate = Calendar.current.date(bySettingHour: hour, minute: minute, second: 0, of: Date())!
                
                let firstTimeInterval = firstDate.timeIntervalSince1970 // get timeInterval
                
                // example run for
                // repeat count 5 and jump 2
                // 2 4 6 8 10
                for i in stride(from: jumpNextDay, to: jumpNextDay * (repeatCount   1), by: jumpNextDay) {

                    // create next day
                    // 86400 next time interval added to first time interval
                    
                    // create time interval from first date

                    // 2 next day = firstTimeInterval   2 * 86400
                    
                    let timeIntervalForTrigger = firstTimeInterval   Double((i * 86400))
                    
                    // create date from time interval
                    let date = Date.init(timeIntervalSince1970: timeIntervalForTrigger)
                    
                    // create datecomponnet
                    let dateComponents = date.getDateComponents()
                    
                    let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

                    let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
                    center.add(request)
                }
            }
        }
    }
 

и позвонить:

 let date = self.timepPicker.date
        let calendar = Calendar.current
           let hour = calendar.component(.hour, from: date) // get hour
        let minutes = calendar.component(.minute, from: date) // get minute

        self.setLocalNotification(repeatCount: 2, jumpNextDay: 2, hour: hour, minute: minutes)
 

Комментарии:

1. Извините, ваш код работает, но когда я меняю интервал (количество дней, как часто получать уведомления), уведомления приходят каждый день. Так работает или по дням, или по времени, но я стараюсь совместить две вещи. Например, настройте уведомления каждые X дней (которые я выбираю с помощью средства выбора) в X время (которое я также выбираю с помощью средства выбора). В этом и заключается проблема. 🙁 потому что, если я выбираю интервал, я использую UNTimeIntervalNotificationTrigger, если я выбираю время, я использую UNCalendarNotificationTrigger

2. добавьте новый подход к моему ответу, посмотрите еще раз

3. Да, это работает, уведомления приходят каждые 2 дня и повторяются 2 раза, как в этой строке (self.setLocalNotification(repeatCount: 2, jumpNextDay: 2, час: час, минута: минуты)) в то время, которое я выбрал из TimePicker. Но у меня также есть другой сборщик для интервала, поэтому я не понимаю, как я могу сделать «jumpNextDay» из сборщика и повторять его бесконечно … p.s. Я новичок, поэтому прошу прощения, если я не понимаю простых вещей

4. Если вы хотите, вы можете отправить пользовательский интерфейс, который вам нужно реализовать вместе с рабочим процессом, здесь, чтобы я мог вам помочь.

5. Я обновил свой вопрос и добавил фотографию 🙂