I am trying to set up daily repeated notifications with swift.
I am able to set up the notification by using
var dateComponents = DateComponents()
dateComponents.hour = 17
dateComponents.minute = 00
But I want the user to be able to change that, I set up a date picker and changed it to time only
In the date picker I was able to get it to save by doing the following
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
loadDate(animation: true)
}
func saveDate() {
UserDefaults.standard.set(TimePicker.date, forKey:dateKey)
}
func loadDate(animation: Bool) {
guard let loadedDate = UserDefaults.standard.object(forKey: dateKey) as? NSDate else { return }
TimePicker.setDate(loadedDate as Date, animated: animation)
}
How can I pass what was selected from hour and minute to the notification time? Also how would I be able to convert the time to 24 hours that way if they select 5 pm it goes to the date component as 17?
Thanks for any help
This is how I have the view controller. inside viewdidload. and then the timepicker is inside another viewcontroller
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound ]){(grandted,error)in }
let content = UNMutableNotificationContent()
content.title = "Title"
content.body = "Body"
var dateComponents = DateComponents()
dateComponents.hour = 17
dateComponents.minute = 18
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let uuidstring = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidstring, content: content, trigger: trigger)
center.add(request) {(error) in}
Since you dong time selection on another view controller (second), you need to notify first (main) view controller that date have been changed.
Here many different ways to do it. Passing Data between View Controllers
Choose any you like, for this example I will use notifications:
extension Notification.Name {
/// Notification used to pass user selected date
static let dateChanged = Notification.Name(rawValue: "DateChanged")
}
In second controller update save function:
func saveDate() {
UserDefaults.standard.set(TimePicker.date, forKey:dateKey)
/// Send notification with new time
NotificationCenter.default.post(name: .dateChanged, object: TimePicker.date)
}
In same time in main controller you need to subscribe to notifications:
deinit {
/// We need to unsubscribe from notifications, otherwise app can crash
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
...
/// Subscribe to notifications
NotificationCenter.default.addObserver(
self,
selector: #selector(dateChanged(_:)),
name: .dateChanged,
object: nil
)
}
/// This method will be called when controller receive notification
/// It need to be annotated with @objc
@objc func dateChanged(_ notification: Notification) {
let date = notification.object as! Date
let components = Calendar.current.dateComponents([.hour, .minute], from: date)
setNotification(with: components)
}
/// By always using same ID for local notifications
/// You can easily remove them when time changes
private static let notificationID = "MyAppNotificationID"
func setNotification(with components: DateComponents) {
/// Remove previously planned notification
center.removePendingNotificationRequests(withIdentifiers: [MainVC.notificationID])
/// Create new notificaion
let content = UNMutableNotificationContent()
content.title = "Title"
content.body = "Body"
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let request = UNNotificationRequest(identifier: MainVC.notificationID, content: content, trigger: trigger)
/// Add to center
center.add(request) {(error) in}
}