I have created a method to schedule notifications and calling in the SceneDelegate. I'm setting a time range which can be later changed from the settings of the App. Right now it works but if I set some small range to test, the notifications come even after that range. Also notified sometimes if I set range from 9 AM to 10 PM, notifications come even after 10 PM. I added some logic to schedule number of notifications based on current time and remaining final time but it's not working that well. I'm not sure why notifications are even coming even though I have specified the end time. Here is the method that I have written to schedule notifications between some time range:
func scheduleNotifications(pendingNotications: Int) {
// Default min and max random notifications values
var minValue = 5
var maxValue = 10
// Default Start and End time for Notifications
var startTime = 9
var endTime = 21
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Test"
content.body = "Test Notification"
content.sound = UNNotificationSound.default
// Calculate the time range for notifications
let calendar = Calendar.current
let now = Date()
let startOfDay = calendar.startOfDay(for: now)
let startDate = calendar.date(bySettingHour: startTime, minute: 0, second: 0, of: startOfDay)!
let endDate = calendar.date(bySettingHour: endTime, minute: 0, second: 0, of: startOfDay)!
let timeRange = endDate.timeIntervalSince(startDate)
// Calculate the number of notifications to send today
let numberOfNotifications: Int
if pendingNotications != 0 {
minValue = Int.random(in: 0...minValue)
maxValue = Int.random(in: minValue...maxValue)
if now < startDate || now < endDate {
numberOfNotifications = Int.random(in: minValue...maxValue)
}
else {
numberOfNotifications = 0
}
}
else {
// Loaded for first time
if now < startDate {
numberOfNotifications = Int.random(in: 5...10)
} else if now < endDate {
let remainingTimeRange = endDate.timeIntervalSince(now)
let remainingMinutes = Int(floor(remainingTimeRange / 60))
var maxNotifications = Int.random(in: 5...10)
if remainingMinutes < 45 {
maxNotifications = 1
numberOfNotifications = Int.random(in: 0...maxNotifications)
} else if remainingMinutes < 120 {
maxNotifications = 2
numberOfNotifications = Int.random(in: 1...maxNotifications)
} else if remainingMinutes < 180 {
maxNotifications = 3
numberOfNotifications = Int.random(in: 1...maxNotifications)
} else if remainingMinutes < 240 {
maxNotifications = 6
numberOfNotifications = Int.random(in: 1...maxNotifications)
}
else {
numberOfNotifications = Int.random(in: 5...10)
}
} else {
numberOfNotifications = 0
}
}
// Schedule only if number of notifications is not 0
if numberOfNotifications > 0 {
let intervalBetweenNotifications = timeRange / TimeInterval(numberOfNotifications)
for i in 1...numberOfNotifications {
let randomTimeInterval = TimeInterval.random(in: 0...intervalBetweenNotifications)
let notificationDate = startDate.addingTimeInterval(TimeInterval(i) * intervalBetweenNotifications + randomTimeInterval)
let dateComponents = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: notificationDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let userInfo = ["notificationFiredAt": notificationDate]
content.userInfo = userInfo
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request) { error in
if let error = error {
debugPrint(error)
}
}
if UIApplication.shared.applicationState != .active {
center.add(request) { error in
if let error = error {
debugPrint(error)
}
}
}
}
}
DispatchQueue.main.async {
debugPrint("totalNotifications - ", numberOfNotifications)
let vc = HomeViewController()
self.navigationController?.pushViewController(vc, animated: true)
}
}