Scheduling local notifications to repeat daily from tomorrow in Swift - ios

I'm trying to schedule a local notification to fire every day (i.e. repeats), at a specific time, but from tomorrow.
i.e "Trigger a notifcation every day at 8pm, from tomorrow"
I've been using this SO question as guidance, and I believe I am doing what it says but I am still getting a notification today when I run the following code (if I schedule the notification before 8pm for instance):
func testDateNotification(){
let content = UNMutableNotificationContent()
content.title = "Test"
content.body = "This is a test"
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date())
let userCalendar = Calendar.current
var components = userCalendar.dateComponents([.hour, .minute], from: tomorrow!)
components.hour = 20
components.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let request = UNNotificationRequest(identifier: "test", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
if ((error) != nil){
print("Error \(String(describing: error))")
}
}
}

import UserNotifications
Check for user permission
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]) {
if $0 { } }
Add notification
let fromDate = Date(timeIntervalSince1970: Double(0.0))
let dateComponent = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: fromDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: true)
print(trigger.nextTriggerDate() ?? "nil")
let content = UNMutableNotificationContent()
content.title = "title"
content.body = "body"
let request = UNNotificationRequest(identifier: "identify", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) {
if let error = $0 {
print(error)
return
}else {
print("scheduled")
}
}

Related

iOS Local Notifications after first and last use

I am trying to set up local notifications that are triggered under two circumstances:
- An x number of days after the first use of the app
- In case the user has gone an x number of days without using the app
Is this possible? All the information I have found online is about setting notifications to go off at a specific time, but how can I send depending on the app's first and last use?
First of all, you need a request to register the notifications, and after the notification is granted, you can call the functions that firing the notifications on the specific time.
In AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let center = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .sound]
center.requestAuthorization(options: options, completionHandler: { granted, error in
if granted {
self.setNotificationForFirstTimeUseApp()
self.setNotificationForLastTimeUseApp()
print("Notification is granted")
} else {
print("Notification is not granted")
}
})
return true
}
Create the functions for firing the notification on a specific time:
func setNotificationForFirstTimeUseApp() {
// Check the app, if it is opened before
if let _ = UserDefaults.standard.value(forKey: "appOpened") as? Bool {
return
}
// Save a flag on preferences that it tells the app is opened for the first time
UserDefaults.standard.set(true, forKey: "appOpened")
let content = UNMutableNotificationContent()
content.title = "Using for the first time - Notification" // Add your own title
content.body = "Awesome thank you for using this application!" // Add your own description
content.sound = UNNotificationSound.default
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = NSTimeZone.local
// Specific the time you want to fire the notification (after some days, hours, minutes...)
if let date = Date.getDateByAdding(days: 0, hours: 0, minutes: 0, seconds: 5) {
let componentsForFireDate = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second, .timeZone], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: componentsForFireDate, repeats: false)
let identifier = "firstTimeUseApp"
let request = UNNotificationRequest(
identifier: identifier,
content: content,
trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: { error in
if error != nil {
if let error = error {
print("Something went wrong: \(error)")
}
}
})
center.getPendingNotificationRequests(completionHandler: { requests in
print(String(format: "PendingNotificationRequests %i", requests.count))
for req in requests {
let trigger = req.trigger
if let trigger = trigger {
print("trigger \(trigger)")
}
}
})
}
}
func setNotificationForLastTimeUseApp () {
let content = UNMutableNotificationContent()
content.title = "Using for the last time - Notification" // Add your own title
content.body = "You have not used the application for a long time!" // Add your own description
content.sound = UNNotificationSound.default
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = NSTimeZone.local
// Specific the time you want to fire the notification (after some days, hours, minutes...)
if let date = Date.getDateByAdding(days: 0, hours: 0, minutes: 0, seconds: 10) {
let componentsForFireDate = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second, .timeZone], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: componentsForFireDate, repeats: false)
let identifier = "lastTimeUseApp"
let request = UNNotificationRequest(
identifier: identifier,
content: content,
trigger: trigger)
let center = UNUserNotificationCenter.current()
// Remove pending notifications
center.removePendingNotificationRequests(withIdentifiers: [identifier])
center.add(request, withCompletionHandler: { error in
if error != nil {
if let error = error {
print("Something went wrong: \(error)")
}
}
})
center.getPendingNotificationRequests(completionHandler: { requests in
print(String(format: "PendingNotificationRequests %i", requests.count))
for req in requests {
let trigger = req.trigger
if let trigger = trigger {
print("trigger \(trigger)")
}
}
})
}
}
And finally, add this function. It will calculate a future date by adding days, hours, minutes and seconds, from now.
extension Date {
static func getDateByAdding(days: Int, hours: Int, minutes: Int, seconds: Int) -> Date? {
let currentDate = Date()
var dateComponent = DateComponents()
dateComponent.day = days
dateComponent.hour = hours
dateComponent.minute = minutes
dateComponent.second = seconds
let futureDate = Calendar.current.date(byAdding: dateComponent, to: currentDate)
return futureDate
}
}
I hope this answer will help you with your issue!

decrement int from string time 4:01 to 3:51 in swift

hi I want to make a local notification from string time, I want the notification launch 10 minute before given time. I have trouble how to make the time from 4:01 into 3:51, please help. this is my code
let a = "4:01"
func startNoftification(prayer: String) {
let time = prayer.split(separator: ":").map { (x) -> Int in
return Int(String(x))!
}
let content = UNMutableNotificationContent()
content.title = "Adzan"
content.body = "it's time to sholat dzuhur"
let gregorian = Calendar(identifier: .gregorian)
var component = gregorian.dateComponents([.year, .month, .day, .hour, .minute, .second], from: Date())
component.hour = time[0]
component.minute = time[1] - 10
guard let date = gregorian.date(from: component) else { return }
let triggerDaily = Calendar.current.dateComponents([.hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let request = UNNotificationRequest(identifier: "Hijrah", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
if let err = error {
print("Notif error:", err)
return
}
}
}
Is this what you need?
let time = "4:01"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm"
guard let date = dateFormatter.date(from: time) else {
return
}
let targetTime = Date(timeInterval: -(10 * 60), since: date) // Change time interval to required value in seconds
let targetTimeString = dateFormatter.string(from: targetTime)
print(targetTimeString) // Prints 3:51
Or if your countdown time has a lot of time components, use DateComponents.
var dateComponents = DateComponents()
dateComponents.minute = -10
// Other components
if let targetTime = Calendar.current.date(byAdding: dateComponents, to: date)
print(dateFormatter.string(from: targetTime))
}
Here I have solution combine with rakesha Shastri answer, hopefully it can helps others.
First import UserNotification in appDelegate and in your controller
import UserNotification
and add code for didFinishWithLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge]) { (granted, error) in
if let err = error {
print("Notifications permission denied because:", err)
return
}
if granted {
print("Notifications permission granted.")
}
}
}
and you can make a function and add string time parameters either from API or arbitrary string, since I'm not using function so I pass my solution in viewDidLoad
let adzan = "4:01"
let content = UNMutableNotificationContent()
content.title = "Adzan"
content.body = "It's time for sholat"
content.sound = UNNotificationSound.default
// Format the date first from string time
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
//addingTimeInterval is where you want to set notification before or after deciding time in this case I set it 10 minute before deciding time
guard let date = dateFormatter.date(from: adzan)?.addingTimeInterval(-600) else { return }
// and convert our date into dateComponents
let triggerDate = Calendar.current.dateComponents([.hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)

swift display local notification even the app terminated

hello i want to send notification like daily reminder even the app terminated not working in background how i can do it and this my code
func soundNotification(){
let prayers = ["fajer","dohor","asr","maghreb","isha"]
let content = UNMutableNotificationContent()
content.title = "\(prayers[indexOfNextPrayer + 1]) azan will be after 5 minutes"
content.badge = 1
content.sound = UNNotificationSound(named: "salah.mp3")
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let request = UNNotificationRequest(identifier: "azanSoon", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
func soundNotification(){
let prayers = ["fajer","dohor","asr","maghreb","isha"]
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let content = UNMutableNotificationContent()
content.title = "\(prayers[indexOfNextPrayer + 1]) azan will be after 5 minutes"
content.body = " "
content.badge = 1
content.sound = UNNotificationSound(named: "salah.mp3")
let request = UNNotificationRequest(identifier: "azanSoon", content: content, trigger: trigger)
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("error: \(error)")
}
}
}
Trigger local Notification at date and time.
func scheduleNotification(at date: Date, message:String) {
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents(in: .current, from: date)
let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute)
let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: false)
let content = UNMutableNotificationContent()
content.title = "Reminder"
content.body = message
content.sound = UNNotificationSound.default()
let request = UNNotificationRequest(identifier: "textNotification", content: content, trigger: trigger)
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("error: \(error)")
}
}
}

how to fire local notifications on particular days rather than current weekday

I'm working on an Alarm app. While setting up the alarm, user selects days which are getting stored in an array. But I'm not getting correct weekday when trying to place the value while making notification. In my code I'm getting weekdays in "daysValue" ([0,1,1,1,0,0,0], means alarm is set for monday, tuesday and wednesday) but I'm getting no clue how to pass these values in trigger date. Here's the code
var daysValue: [Int]
daysValue = AlarmController.shared.days
print(daysValue)
for _ in daysValue
{
for ind in 0...countNum
{
guard let fireDate = alarm.fireDate else { return }
print(fireDate)
let date = fireDate.addingTimeInterval((1.0*Double(ind)) * 60.0)
print(date)
let weekday = Calendar.current.component(.weekday, from: date)
print(weekday)
let triggerDate = Calendar.current.dateComponents([.weekday, .hour, .minute, .second], from: date)
DispatchQueue.main.async
{
print(triggerDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: true)
let request = UNNotificationRequest(identifier: "\(alarm.uuid)\(ind)", content: notificationContent, trigger: trigger)
UNUserNotificationCenter.current().add(request)
{
(error) in
if let error = error
{
print("Unable to add notification request, \(error.localizedDescription)")
}
}
}
}
}

swift create user notification

I want to create a userNotification that'll be shown in Notification Center while the app is running.
Clicking the notification will terminate the app.
Which trigger needs to be used?
How do I achieve this functionality?
Try this.
func scheduleNotification(at date: Date, body: String) {
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents(in: .current, from: date)
let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute)
let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: false)
let content = UNMutableNotificationContent()
content.title = "Dont Forget"
content.body = body
content.sound = UNNotificationSound.default()
let request = UNNotificationRequest(identifier: "textNotification", content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
//UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("Uh oh! We had an error: \(error)")
}
}
}

Resources