How to repeat local notification once fired at a particular time - ios

I am currently making an alarm clock app and I am currently stuck at possibly just a misunderstanding. I want to launch a local notification at a specific time and repeat at a time interval. I have been getting a couple ideas and this (https://makeapppie.com/2017/01/31/how-to-repeat-local-notifications/) program is close to what I want it to be but I want it to go off at a certain time and then repeat at a single interval.
After user inputs information, the program will spit out:
timeIntervalSeconds, the interval that user wants the notifications in (in seconds)
timeStart, when the notifications will start
timeEnd, when the notifications will end if the user doesn't stop them
Any suggestions would be greatly appreciated.
Thank you!

To launch notification on specific time use below code.
let gregorian = Calendar(identifier: .gregorian)
let now = Date()
var components = gregorian.dateComponents([.year, .month, .day, .hour, .minute, .second], from: now)
// Change the time to 10:00:00 in your locale
components.hour = 10
components.minute = 0
components.second = 0
let date = gregorian.date(from: components)!
let triggerDaily = Calendar.current.dateComponents([.hour,.minute,.second,], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let request = UNNotificationRequest(identifier: CommonViewController.Identifier, content: content, trigger: trigger)
And to repeat notifications on specific time interval use below code in trigger.
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 120, repeats: true) // it repeats after every 2 minutes

Since Apple provide only limited list of intervals for auto repeat of notifications you can try to do next to use custom intervals:
When a notification got fired you should calculate date & time for next notification and just schedule it on desired time.

Related

Local notification cancel for particular time period

I want to fire local notification on a particular time based just liked water notification.
Like user can set wake up time & go to bed time n drink water notification for every 2 hours so how can i set that between goto bed to wake up time my local notification won;t fire, other than that the notification will fire for every 2 hours..
Please help me.
Thanks
What you can do is to obtain the hours in between the wake up time and sleep time with the frequency of what you wish your notification to fire off.
Firstly, you would need to function to create a local notification that repeats during a particular hour everyday.
func createNotification(title: String, body: String, hour: Int, repeats: Bool, identifier: String) {
//calendar
let calendar = Calendar.current
let content = UNMutableNotificationContent()
content.title = title
content.body = body
let today = Date()
let futureDate = calendar.date(byAdding: .hour, value: hour, to: today)
let hourComponent = calendar.dateComponents([.hour], from: futureDate!)
let trigger = UNCalendarNotificationTrigger(dateMatching: hourComponent, repeats: repeats)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
center.add(request, withCompletionHandler: {(error) in })
}
Secondly, place this code in your viewDidLoad() or the place you wish to set the notifications. What I am doing here is obtaining the wakeup hour and sleep hour and then finding the number of notifications that has to be made using the frequency that I want by dividing the difference in hour with the frequency.
I end of by creating a for loop that creates the notification based on the time that I add to the wakeup hour. eg. First notification fires of at 6am + 1x2 = 8am, second notification fires of at 6am + 2x2 = 10am
//calendar
let calendar = Calendar.current
//set the wakeup and sleep hour
let wakeupHour = 6 //6am
let sleepHour = 18 // 6pm
//Obtain starting time using date components
let wakeup = DateComponents(calendar: calendar, hour: wakeupHour)
//Obtain ending time using date components
let sleep = DateComponents(calendar: calendar, hour: sleepHour)
//calculate the number of hours between the two time
//obtain number of hour difference
let hourDifference = calendar.dateComponents([.hour], from: wakeup, to: sleep)
//how many hours do you want
let frequency:Int = 2
//how many notifications will there be between the wakeup and sleeptime
let numberOfNotifications:Int = hourDifference.hour! / frequency
//create the notifications
for num in 1...numberOfNotifications {
//hour that each notification will fire off
let hour = wakeupHour + frequency * num
createNotification(title: "Drink Up", body: "Drink Up", hour: hour, repeats: true, identifier: "drink\(hour)")
}
I'm still learning swift so this may not be the most efficient way of solving this problem but I hope this helps!

Repeat local notification every n days

I'm trying to create application that will send local notifications every n days.
I has DailyRepeat structure that contains notification info:
struct DailyRepeat: BaseRepeat {
var title: String
var body: String
var date: Date
var day: Int
}
And method that schedule notification:
func notifyDaily(at notification: DailyRepeat) {
let content = generateContent(title: notification.title, body: notification.body)
let dateComponents = DateComponents(day: notification.day, hour: notification.date.time.hours, minute: notification.date.time.minutes)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
notificationCenter.add(request)
}
My first thought was to create UNCalendarNotificationTrigger on first fire date, than handle notification and set UNTimeIntervalNotificationTrigger, but unfortunately I cannot find the way to handle notification receive without user interaction.
Any thoughts how it should work?
As per the documentation if you want the notification to repeat you need to set repeatable constraints for the date components.
So to set a notification to run every morning at 8:30AM you would just set the hour and the minute and set it to repeat.
var date = DateComponents()
date.hour = 8
date.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
I don't think that you can use repeats to repeat every x number of days, you can set specific days of the week, or dates of the month, but not every n days.
You could set a TimeInterval of x number of days and repeat that, but getting the exact time to start it might be tricky.

UNCalendarNotificationTrigger with start date

I am trying to make a reminder app and I am having a hard time trying to set a start date for my reminders. I am able to make local Notification work with the code below. With this code, I am able to get local notification every Tuesday at the time set by the user (Indicated by the "hour" and "minute").
if tuesdayIsChecked == true {
AlarmSupportFileX.tuesdaySelectedBool = true
hour = hourDateFormatter.string(from: datePicker.date)
minute = minuteDateFormatter.string(from: datePicker.date)
var dateComponents = DateComponents()
dateComponents.weekday = 3
dateComponents.hour = Int(hour)
dateComponents.minute = Int(minute)
print(dateComponents)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let requestIdentifier = "\(randomGeneratedString)Tuesday"
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
//Handle error
})
}
My issue is that I only want it to trigger on the Date chosen by user.
Example: If I use my code above on 12th Nov 2018 (Monday), a notification will trigger on 13th Nov 2018 (Tuesday) and all the Tuesday that follows.
Assuming user select alarm to trigger on tuesday (dateComponents.weekday = 3).If user set a notification on 12th Nov(Monday) and they selected a start date on 25th Nov(Sunday), I want it to only show the notification on 27th Nov(Tuesday) and all the Tuesday that follows. How can I achieve this?
This is not possible using only UNCalendarNotificationTrigger.
You would need to set up some sort of mechanism for the app to set up that notification the week of the Tuesday.
One way to do this could be:
check if the selected date is this week
-> IF TRUE: register notification
-> IF FALSE: write to UserDefaults the date.
In an didBecomeActive() or viewDidLoad() you could then load the date from UserDefaults and check if the date is in this week, if that's the case, you register the notification.

Set repeat notification trigger using DateComponents

Currently working on an App need set different type of repeat rule of notification
Like repeat everyday, workday, weekday or several days of the week.
var dateInfo = DateComponents()
dateInfo.hour = 7
dateInfo.minute = 0
dateInfo.weekday = 1
let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: true)
Using this API can only add one day of the week at each time,
is there any simple way.
appreciated

Notification with weekly repeat, and specific start date

I can set a UNNotification to fire at a specific date/time, like so
let components = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: fireTime)
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
And I can set one to fire at a specific time on a specific day of the week, every week, like so
var components = Calendar.current.dateComponents([.weekday], from: nextMondayDate)
components.setValue(10, for: .hour)
let trigger = UNCalendarNotificationTrigger.init(dateMatching: triggerComps, repeats: true)
But is there any way I can set a UNNotification to fire at a specific date and time, and then to repeat every week on that weekday and time?
Specifically, I would like to set a notification to fire every Monday at 10am except next Monday.
if you just want to skip only next monday, you can calculate next to next monday date and set in the components on the place of nextMondayDate keeping rest of the setting as it is, like repeat true.

Resources