Change Repeating Reminder's Content Daily - swift

In my app, I ask the user to set up a repeating reminder. In this reminder, I would like the body to say something different each day. For example, I have over 500 quotes in my Firebase db and I want my reminder to show a new quote each day. How can I programmatically change the body of the reminder each day without user interaction?
#IBAction func saveButtonPressed(_ sender: Any) {
let content = UNMutableNotificationContent()
let identifier = "myApp"
content.title = "myApp"
content.body = "I want to change this programatically each day"
let trigger = UNCalendarNotificationTrigger(dateMatching: Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: reminderTime.date), repeats: true)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request){
(error) in
if error != nil
{
print("here error in setting up notification")
print(error!)
}
else
{
print("notification scheduled")
}
}
}

Unfortunately, you can not handle the LocalNotification showing moment. You just tell the system when to show your notification and the system show it without calling your application.
But you can add multiple notification requests at once (up to 64). For example, all notifications for the next month and update your notifications on app launch. Just make sure that your notification requests has different identifiers.
For example, you create 30 notifications and user receives them for 5 days. Then he opens your app and you add 5 notifications more.
If you'll need to remove some of the pending notifications, you can make it using the following method.
let center = UNUserNotificationCenter.current()
center.removePendingNotificationRequests(withIdentifiers: identifiers)

Related

ios - waiting 24hrs to send a notification

Our application sends a notification every morning at 8am to greet the user and remind him to complete a task. Here is the script we are using:
let center = UNUserNotificationCenter.current()
center.removePendingNotificationRequests(withIdentifiers: ["dailyReminder"])
let content = UNMutableNotificationContent()
content.title = "Good morning"
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)
This is called after the user finishes the day's task so that they are prompted the next day. However, some people finish the task before 8am. In those cases we'd like for the notification to be sent at 8am of the next day.
How could I calculate if the script runs before or after 8 and add 24 hrs accordingly?
Since this is run locally you could just save the last time the function was sent by holding it in a UserDefault. For example, add the following to the code to save when the user has last done a task:
UserDefaults.standard.set("/(youWillWriteAFunctionForDate)", forKey: "checkTaskOfDate")
Then you can simply check if it was sent today, and plan accordingly:
defaults.string(forKey: "checkTaskOfDate") ?? "Never Done"

How do you send notifications based on user input? SWIFT

How do you set the notification time to match the input of the user?
If a notification reminds the user of new content (i.e the word of the day), is that considered a local notification or a push notification?
The userSelectedTime variable is created when they press done, but I don't know how to pass it on to my sendNotification function which uses DateComponents() to set the time.
#objc func donePressed() {
// formatter
let formatter = DateFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .short
var userSelectedTime = timeTextField.text
userSelectedTime = formatter.string(from: timePicker.date)
print(userSelectedTime)
self.view.endEditing(true)
}
func sendNotification() {
// Default time 10:30, but base it on userSelectedTime if not void
var dateComponents = DateComponents()
dateComponents.hour = 10
dateComponents.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: createNotificationContent(for: myData), trigger: trigger)
center.add(request)
}
First I will answer your question 2. - This mostly depends on where that information is coming from. If the "word of the day" is something you have stored internally inside the app, you can schedule a local notification with that information. However, if you want to change the word of the day externally every day, you will have to create a push notification to achieve this. (At least the only way to make it work properly). Push notifications would require some sort of service to push those to the app so the easiest for you is to go with the local notifications.
To summarize question 2:
Local notification: Something that is created within the app.
Push notification: Information 'pushed' from an external source.
Question 1:
You can do this in a number of ways. What I would recommend from looking at what you already have is to create the date components with the selected time and pass those components to your 'sendNotification()' function.
As an example:
// Capture the time and turn them into components
func donePressed() {
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute, .month, .year, .day], from: timePicker.date)
sendNotification(components: components)
}
// Schedule the notificaiton based on components
func sendNotification(components: DateComponents) {
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: createNotificationContent(for: myData), trigger: trigger)
center.add(request)
}
Now... I can't see all your code, so I assume that what else you got going is working properly. But I hope you get the concept. I would however recommend creating a separate class like "NotificationScheduler" to handle these things, that way you will be able to separate things a bit more.

Is it possible to mutate the content of a local notification in swift?

In the next version of my app, I want to integrate the possibility that the user can enable weekly reports like the screentime feature from apple.
I know how to setup Local Notifications (The code is already working for other types of notifications like reminders for events), but for this idea, I need the notification text to be updated shortly before firing because I don`t know the exact content of the notification when I add it to the NotificationCenter.
Is there a function which is called shortly before firing or how would I do this?
This is my working code for scheduling notifications:
fileprivate func generateNotification(title: String, body: String, triggerDate: DateComponents) -> String{
//Trigger
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: false)
//Content
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.sound = UNNotificationSound.default
//Request
let identifier = UUID().uuidString
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.add(request) { (error) in
if let error = error {
print("Error \(error.localizedDescription)")
}
}
return identifier
}

Trigger Xcode notification after certain time has passed (Swift 3)

I've tried a lot of things but I just can't seem to figure out which command to use to trigger an alert in (example) 2 days, or 5 hours. Can anyone help me out? What I'd like to be able to do is the following:
var number = 3
var repeat = day
*Code with 'number' and 'repeat' in it.*
So in this case it would send out an alert in 3 days. Anyone here knows how to do that? ^^
Thanks in advance!
First, place this on the top of the file that needs notifications:
import UserNotifications
Then place this in application(_:didFinishLaunchingWithOptions:) of AppDelegate
let notifCenter = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .badge, .sound]
notifCenter.requestAuthorization(options: options, completionHandler: nil)
So now request the Notification as follows:
// timeInterval is in seconds, so 60*60*12*3 = 3 days, set repeats to true if you want to repeat the trigger
let requestTrigger = UNTimeIntervalNotificationTrigger(timeInterval: (60*60*12*3), repeats: false)
let requestContent = UNMutableNotificationContent()
requestContent.title = "Title" // insert your title
requestContent.subtitle = "Subtitle" // insert your subtitle
requestContent.body = "A body in notification." // insert your body
requestContent.badge = 1 // the number that appears next to your app
requestContent.sound = UNNotificationSound.default()
// Request the notification
let request = UNNotificationRequest(identifier: "PutANameForTheNotificationHere", content: requestContent, trigger: requestTrigger)
// Post the notification!
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
// do something to the error
} else {
// posted successfully, do something like tell the user that notification was posted
}
}
This part of code does three things:
Define the trigger
Create the notification context
Post the context
If you intend to continue to work with notifications, look at this tutorial, which also talks about how to react when the user taps on your notification.
Note: UNMutableNotificationContext is mutable, despite the name, UN is just the namespace. Don't get confused!
If you provide a subtitle, it will be between the title and body.
This is the badge property:

How to trigger a WK Notification

What code do I write to trigger a watch kit notification from the watch app itself? For example, if I connect a button from my watch storyboard to my WatchInterfaceController as an action then when pressed it triggers a notification on the watch.
For trigger a notification, first of all you need permission: (declared usually in the ExtensionDelegate)
func askPermission() {
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert,.sound]) { (authBool, error) in
if authBool {
let okAction = UNNotificationAction(identifier: "ok", title: "Ok", options: [])
let category = UNNotificationCategory(identifier: "exampleCategoryIdentifier", actions: [okAction], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
UNUserNotificationCenter.current().delegate = self
}
}
}
For having this working, you need to import (in the ExtensionDelegate) "UserNotifications" and to extend:
UNUserNotificationCenterDelegate
Once you have done that, you can call askPermission where you want, in a way like this:
if let delegate = WKExtension.shared().delegate as? ExtensionDelegate {
delegate.askPermission()
}
Now you have (hopefully) the permission for trigger a notification!
For trigger a notification, you can use a function like this:
func notification() {
let content = UNMutableNotificationContent()
content.body = "Body Of The Notification"
content.categoryIdentifier = "exampleCategoryIdentifier" // Re-Use the same identifier of the previous category.
content.sound = UNNotificationSound.default() // This is optional
let request = UNNotificationRequest(identifier: NSUUID().uuidString,
content: content,
trigger: nil)
let center = UNUserNotificationCenter.current()
center.add(request) { (error) in
if error != nil {
print(error!)
} else {
print("notification: ok")
}
}
}
In order to test watch notifications, you must first create a new build scheme.
Duplicate your watch app scheme, and in the "Run" section, choose your custom notification as the executable.
Now you can run the notification scheme.
Inside the extensions group in your project, under Supporting Files is a file called PushNotificationPayload.json.
You can edit the payload file to try different notifications and categories.