I have an app where the user needs to complete a task every day. If the user does not complete a task, he/she gets a reminder at 8am the next day with a phrase prompting to complete the task.
We would like to send a phrase every morning but we don't want it to be the same phrase every day.
This is what we have right now:
static func scheduleDailyUnwatchedNotification() {
let notificationMessages = ["Phrase one", "Phrase two", "Phrase 3", "Phrase 4", "Phrase 5"]
let totalMessages = notificationMessages.count
let randomIndex = Int.random(in: 0..<totalMessages)
let center = UNUserNotificationCenter.current()
center.removePendingNotificationRequests(withIdentifiers: ["dailyReminder"])
let content = UNMutableNotificationContent()
content.title = "Reminder"
content.body = notificationMessages[randomIndex]
content.sound = .default
var dateComponents = DateComponents()
dateComponents.hour = 8
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: "dailyReminder", content: content, trigger: trigger)
center.add(request)
}
The problem is that even though a random phrase is selected, the notification will always repeat with that same random phrase.
How can we have it repeat with a different phrase?
You’ll need to schedule each different phrased notification manually. However if you’re sending a phrase every day and you have say 50 of them you could schedule each to repeat every 50 days. Then whenever the user opens the app you can always swap around the days the notifications are sent - so the phrases ordering isn’t always the same. It’s not the most ideal but does allow recurring notifications with different titles.
Alternatively if you want to be able to change the notification titles without new app releases/have more control you can use push notifications. This way you can set up a backend to send messages but it does have more overhead from a server perspective.
Related
I'm trying to make an algorithm that receives a time for the first dose of the medicine, and from there it triggers an alarm for X time from now, also selected by the user.
Example: First dose of the medicine was at 12:00 and I want to take it every 8 hours. Therefore, the first alarm must be set at 20:00 and the following, every 8 hours.
The problem is that if I set the first alarm to the desired time + 8, the alarm will not go off at 20, but yes. And if I only use it every 8 hours, I can't set the start time
func notifications(name: String, timeToTime: String, firstTime: String) {
let center = UNUserNotificationCenter.current()
getTimeForNotification(string: firstTime)
let content = UNMutableNotificationContent()
content.title = "It's time to take \(name)"
content.body = "Remember that you must ingest this medicine from \(timeToTime)"
content.sound = UNNotificationSound.default
let timeInterval = handleToInt(time: timeToTime) // * 3600
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: timeInterval,
repeats: true)
let request = UNNotificationRequest(identifier: name, content: content, trigger: trigger)
center.add(request)
}
first time is the variable that stores the time of the first dose, as a double, by the method getTimeForNotification() and timeInterval is the time, ex: 8 in 8, 12 in 12
Below is what I am trying to achieve.
Show local notification to the user about say sunrise/sunset time.
Say sunrise time is at 05:30AM and sunset time at 06:30PM.
Current time is 07:00PM, when the user enables the notification feature then every one hour show
sunrise notification with info time left for sunrise ( that is x hours and y mins left)
Once the time left for sunrise is less than 60 mins, then change the interval from one hour to say 10 mins. Finally when the time left for sunrise is less than 10 mins, then show notification for every minute. When the time for sunrise is reached repeat the same for sunset. This goes on till the user disable this feature via app settings.
Showing a countdown timer is also fine with in a notification if that doesn't drain the battery.
What I have achieved is fire a local notification at a specific time. Appreciate any guidance. I am new to IOS development.
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.categoryIdentifier = "sdf"
if let info = userInfo {
content.userInfo = info
}
content.sound = UNNotificationSound.default()
var comp = Calendar.current.dateComponents([.hour, .minute], from: date)
comp.minute = comp.minute! + 2
let trigger = UNCalendarNotificationTrigger(dateMatching: comp, repeats: false)
//let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
let request = UNNotificationRequest(identifier: "test", content: content, trigger: trigger)
center.add(request)
I am adding a local notification feature to my iOS app which will fire up a notification / alert on a specified time e.g. 7am daily. So I setup the alert using the code below:
let content = UNMutableNotificationContent()
content.title = "Planned transactions due today"
content.body = "You have [NUMBER] scheduled income and [NUMBER] planned expenses due for today."
content.categoryIdentifier = "alarm"
content.userInfo = ["customData": "fizzbuzz"]
content.sound = UNNotificationSound.default
let date = Date(hour: 7, minute: 0, second: 0) //custom initializer from Date extension
let dateComponents = Calendar.current.dateComponents([.hour, .minute], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let request = UNNotificationRequest(identifier: "Reminder", content: content, trigger: trigger)
center.add(request) { (error) in
if let error = error {
print("Error scheduling notification: \(error.localizedDescription)")
}
}
It works perfectly. But what I want to achieve is to add more useful information within the local notification's body, like replacing the [NUMBER] to an actual number which is derrived from a query from core data.
I need help on how to pull this off. I've looked at implementations using UNNotificationServiceExtension and UNNotificationContentExtension. But I can't seem to make it work. I was unable to find any implementations of UNNotificationServiceExtension that applies to local notification – I could be wrong but I think it's only for push notifications.
I've also tried implementing UNUserNotificationCenterDelegate on the AppDelegate to intercept the notification as it is being triggered. func userNotificationCenter(willPresent:) method allows me to get the notification but there seems to be no way for me to change the .content property as it is get-only.
So basically, I just want to be able to change the body content of the notification before it is being displayed.
My solution isn't the best, but to achive this, i do the following at each app launch:
first cancel the next notifications,
then update it with a new content.
It works fine if the app is used at a regular basis.
there is some something called BGTaskScheduler. Apple said that it is a
A class for scheduling task requests that launch your app in the
background.
https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler
Maybe you should check for it
in my app I send a daily notification to remind the user to visit the app.
This notification is locally delivered every day at 1pm.
func scheduleNotifications() -> Void {
for notification in notifications {
let content = UNMutableNotificationContent()
content.title = notification.title
let todaysDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd"
let currentDay = dateFormatter.string(from: todaysDate)
let currentDayInt = Int(currentDay) ?? 0
var datComp = DateComponents()
datComp.hour = 13
datComp.minute = 00
datComp.day = currentDayInt + 1
let trigger = UNCalendarNotificationTrigger(dateMatching: datComp, repeats: true)
let request = UNNotificationRequest(identifier: notification.id, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
guard error == nil else { return }
print("Scheduling notification with id: \(notification.id) on Day \(datComp.day ?? 00) at \(datComp.hour ?? 00) - \(datComp.minute ?? 00)")
}
}
}
As you can see, I added the "current day + 1" lines because if the user opens the app before 1pm, there is no need to deliver the notification on this day.
So every time the user opens the app, I use UNUserNotificationCenter.current().removeAllPendingNotificationRequests() to remove and reschedule the notification for the next day (by recalling the function above).
My issue:
The notification should repeat every day, which it does, as long as the user opens the app.
But if the user does not open the app on one day, there will be no notification on the following days.
Is there a way to mute notifications for the current day so that I don't have to use this "current day + 1"-thing? Or does anyone have a better idea?
Thank you guys.
I think you misunderstood how repeating notifications and your datComp works here.
For example (let's use today's date: May 27)
datComp.hour = 13
datComp.minute = 00
datComp.day = currentDayInt + 1 // in our example it's 28
let trigger = UNCalendarNotificationTrigger(dateMatching: datComp, repeats: true)
means that your notification will get triggered every month on 28th, all parameters your trigger knows is hour, minute, day and by repeating it, will be triggered on every 28th at 13:00.
So the way your app works now is that you set up monthly notification starting from tomorrow, when you open the app you remove that monthly notification and reschedule it for day later. By opening every day it gives you impression that its daily notification but it's not, it's monthly. That's why if you don't open the app nothing shows up next the day, it will show up next month.
You can check my similar explanation here: (top answer there, maybe it is better worded and easier to understand)
Removing scheduled local notification
and my solution for similar problem i had here:
How to set up daily local notification for tasks but don't show it when user completes the task before
I want to make an app just like iOS Reminders app. My problem is the custom repeat part. We can set custom repeats like "Every 2 Months on the third Monday"(the screenshot below) but I don't know how to implement this sort of repeats with User Notification.
What should I have do?
Although the question might be abroad to be fully answered, I would post an answer that should scratch the surface of how you could achieve it by using user notifications.
If you are aiming to let the displaying of the notification is based on a specific date/interval -as you mentioned "Every 2 Months on the third Monday"-, then you should work with UNCalendarNotificationTrigger:
The date and time at which to deliver a local notification.
Example:
import UserNotifications
// first, you declare the content of the notification:
let content = UNMutableNotificationContent()
content.title = "Notification Title"
content.subtitle = "Notification Subtitle"
content.body = "Notification Body"
// now, you should declare the UNCalendarNotificationTrigger instance,
// but before that, you'd need to describe what's the date matching for firing it:
// for instance, this means it should get fired every Monday, at 10:30:
var date = DateComponents()
date.weekday = 2
date.hour = 10
date.minute = 30
// declaring the trigger
let calendarTrigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
// creating a request and add it to the notification center
let request = UNNotificationRequest(identifier: "notification-identifier", content: content, trigger: calendarTrigger)
UNUserNotificationCenter.current().add(request)