how to set local notifications between 8am and 8pm every day - swift

So I am very new to Swift and I'm currently setting a repeating timer every 30 min after the app was launched, but i would like to only send notification between 8 am and 8 pm. Is it possible to do this without setting a reminder for each specific time?
This is how I'm currently doing this.
override func viewDidLoad(){
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.requestAuthorization(options: [.alert, .sound]) { (granted, error ) in
// enable or disable if needed.
if granted {
print("We have permission to send notifications")
} else {
print("We don't have the option to send notifications")
}
}
notificationCenter.removeAllDeliveredNotifications()
notificationCenter.removeAllPendingNotificationRequests()
// The actual notification the user will receive
let notification = UNMutableNotificationContent()
notification.title = "You should have some water"
notification.body = "It has been a long time since you had some water, why don't you have some."
notification.categoryIdentifier = "reminder"
notification.sound = .default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: (60*30), repeats: true)
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: notification, trigger: trigger)
notificationCenter.add(request, withCompletionHandler: nil)
}

Unfortunately you do need to add a notification request for each 30 minute interval in the 8am-8pm window. What is your aversion to this approach? It's a simple for-loop. Instead of using a UNTimeIntervalNotificationTrigger you would use a UNCalendarNotificationTrigger.
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removeAllDeliveredNotifications()
notificationCenter.removeAllPendingNotificationRequests()
let startHour = 8
let totalHours = 12
let totalHalfHours = totalHours * 2
for i in 0...totalHalfHours {
var date = DateComponents()
date.hour = startHour + i / 2
date.minute = 30 * (i % 2)
print("\(date.hour!):\(date.minute!)")
let notification = UNMutableNotificationContent()
notification.title = "You should have some water"
notification.body = "It has been a long time since you had some water, why don't you have some."
notification.categoryIdentifier = "reminder"
notification.sound = .default
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: notification, trigger: trigger)
notificationCenter.add(request, withCompletionHandler: nil)
}

Related

Will this code send a notification on this day every month?

I have this code that should send a notification to the user on the same day every month. However I'm can't simulate this, so I can't test it. I was wondering if any of you could proof check it, to ensure it does send a notification every month.
Thanks
static func addNotification(){
let center = UNUserNotificationCenter.current()
let addRequest = {
let content = UNMutableNotificationContent()
content.title = "Test"
content.subtitle = "Test"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.day = 31
dateComponents.hour = 12
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: "", content: content, trigger: trigger)
center.add(request)
}
center.getNotificationSettings { settings in
if settings.authorizationStatus == .authorized{
addRequest()
}
else{
center.requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
if success{
addRequest()
}
}
}
}
}

Scheduling local notifications to repeat daily from tomorrow

I'm trying to schedule a local notification to fire every day, at a specific time, but from tomorrow.
e.g. "Trigger a notification every day at 2 pm, from tomorrow"
This is how I set up my schedule function.
func scheduleNotifications(date: Date, identfier: String, after: Bool) {
let content = UNMutableNotificationContent()
content.title = "App"
content.body = "Test."
content.sound = .default
content.userInfo = ["Hour": Int(hourFormatter.string(from: date)) ?? 0]
let afterDay = Calendar.current.date(byAdding: .day, value: after ? 1 : 0, to: Date())
var components = Calendar.current.dateComponents([.hour, .minute], from: afterDay!)
components.hour = Int(hourFormatter.string(from: date)) ?? 0
components.minute = Int(minuteFormatter.string(from: date)) ?? 0
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let request = UNNotificationRequest(identifier: identfier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
This code is for daily notification just call it in tomorrow schedule time
func setupNotificationSettings() {
DispatchQueue.main.async {
let content: UNMutableNotificationContent = UNMutableNotificationContent()
content.title = AppName
content.body = "APP_Body"
content.sound = UNNotificationSound.default
let trigger: UNTimeIntervalNotificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 86400, repeats: true)
let request: UNNotificationRequest = UNNotificationRequest(identifier: "\(AppName)_Local", content: content, trigger: trigger)
let center: UNUserNotificationCenter = UNUserNotificationCenter.current()
center.removeDeliveredNotifications(withIdentifiers: ["\(AppName)"])
center.removeDeliveredNotifications(withIdentifiers: ["\(AppName)"])
center.add(request) { (error) in
}
}
}

how to set notifications at custom intervals between custom start and end times

So i have asked a similar question, but this is outside of the scope of that question. I want to give the user the option to customise when the notifications should start and end; then they would choose the intervals of the notifications.
previous question: how to set local notifications between 8am and 8pm every day
This is the function i am using now and was provided by #Robert Crabtree:
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removeAllDeliveredNotifications()
notificationCenter.removeAllPendingNotificationRequests()
let startHour = 7
let endHour = 23
let totalHours = endHour - startHour
let totalNotifications = totalHours * 2
for i in 0...totalNotifications {
var date = DateComponents()
date.hour = startHour + i / 2
date.minute = 30 * (i % 2)
print("setting reminder for \(date.hour!):\(date.minute!)")
let notification = UNMutableNotificationContent()
notification.title = reminderMessages[randomInt].title
notification.body = reminderMessages[randomInt].body
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: notification, trigger: trigger)
notificationCenter.add(request, withCompletionHandler: nil)
}
I fixed it by doing this if you have any other suggestions on how to do this better, please let me know.
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removeAllDeliveredNotifications()
notificationCenter.removeAllPendingNotificationRequests()
let startHour = 7
let endHour = 23
let intervals = 20
let totalHours = endHour - startHour
let totalNotifications = totalHours * 60 / intervals
for i in 0...totalNotifications {
var date = DateComponents()
date.hour = startHour + (intervals * i) / 60
date.minute = (intervals * i) % 60
print("setting reminder for \(date.hour!):\(date.minute!)")
let notification = getReminder()
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: notification, trigger: trigger)
notificationCenter.add(request, withCompletionHandler: nil)
}

DateComponents and Notifications Not Showing

I have made a to do list app. In the app, the user can select 1 of 4 buttons to set a notification. Immediate, morning, afternoon and evening. Currently, the evening and immediate work but the morning and afternoon are not working and I am unsure why.
Here is my code for the evening:
#IBAction func eveningTapped(_ sender: Any) {
eveningEnabled = true
morningEnabled = false
lockscreenEnabled = false
afternoonEnabled = false
}
if eveningEnabled == true {
var dateComponents = DateComponents()
dateComponents.hour = 18
dateComponents.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let content = UNMutableNotificationContent()
content.title = taskTextField.text!
content.body = DescTextField.text!
content.sound = UNNotificationSound.default()
content.badge = 1
let identifier = "UYLLocalNotification"
let request = UNNotificationRequest(identifier: identifier,
content: content, trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
if error != nil {
// Something went wrong - another alert
}
})
}
This works completely fine but the morning doesn't work, here is the code:
#IBAction func morningTapped(_ sender: Any) {
morningEnabled = true
lockscreenEnabled = false
afternoonEnabled = false
eveningEnabled = false
}
if morningEnabled == true {
var dateComponents = DateComponents()
dateComponents.hour = 07
dateComponents.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let content = UNMutableNotificationContent()
content.title = taskTextField.text!
content.body = DescTextField.text!
content.sound = UNNotificationSound.default()
content.badge = 1
let identifier = "UYLLocalNotification"
let request = UNNotificationRequest(identifier: identifier,
content: content, trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
if error != nil {
// Something went wrong - another alert
}
})
}
Since your code is absolutely identical (except the DateComponents) in both actions, there should be no difference when running.
But as you have a difference ('morning' is not working) the reason MUST be somewhere else (and not in the code, that you posted here). Maybe your tapAction for morning is not correctly connected in the InterfaceBuilder?
If you would post more code, we could probably better help finding the bug.
First you should check, wether your tapAction is being performed, when you tap. You can do this by adding a log command, like this:
print("Morning was tapped")
and put this code into your tapAction. Then you should get this log on your log console, after having tapped the corresponding button.

iOS 10 UserNotification Framework. Calendar Trigger

I am on iOS 10.3.2 Beta 4 and xcode 8.3.2. I am attempting to fire a notification at the same time daily, however the notifications never seem to fire. If I do not use the calendar trigger and use the timeinterval trigger they work as expected.
Here is my code
let content = UNMutableNotificationContent()
content.title = "Daily Notification"
content.subtitle = ""
content.body = NSLocalizedString("Hello I am a notification", comment: "Comment")
content.badge = 1
content.sound = UNNotificationSound.default()
let calendar = Calendar.current
var dateComponents = calendar.dateComponents([.day, .month, .year, .hour], from: Date())
dateComponents.hour = 14
dateComponents.minute = 55
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
NSLog("Setting daily notification - \(dateComponents)")
let request = UNNotificationRequest(identifier: "dailyWarning", content: content, trigger: trigger)
center.add(request, withCompletionHandler: { error in
if error != nil {
NSLog("Error occurred")
} else {
NSLog("Request added successfully: %#", request)
}
})
Try creating your trigger like this:
var dateComponents = DateComponents()
dateComponents.hour = 14
dateComponents.minute = 55
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true) // Setting repeats to true will trigger the notification daily
For more information about why providing just the hour and minutes is sufficient see the explanation above Listing 1 in the documentation found here.