Multiple notifications in Xcode, Swift 3 - swift

first I'd like to say that I've been searching for the answer to my question quite a bit but the only things I've found so far are answers for older versions of Swift or answers that don't specifically answer my question.
Background info:
I'm trying to develop an app that can remind you in a set interval. Now this works, given that you only set 1 reminder. However if I set the interval to be 20 seconds, launch the app, set 2 notifications and close the app only the second notification shows in 20 seconds. The first notification is being overwritten by the second one.
Question: How can I make sure that all of my notifications, requested by the user, actually get sent and that no notification overrides the previous one?
Code for the notification:
let tijd = 20 //20 is just for the test, normally there is more code to it
// Notification
let content = UNMutableNotificationContent()
content.title = "Notification title"//title
content.body = "Notification body" //body
content.badge = 1
content.sound = UNNotificationSound.default()
// Timer
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval(tijd), repeats: false)
let request = UNNotificationRequest(identifier: "timerDone", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
This code is stored in a UITableView cell.

Okay I figured it out!
https://stackoverflow.com/a/41892828/7385440
This answer lead to the same problem I had. I had to make the identifier different for every notification! So my code now is:
let request = UNNotificationRequest(identifier: bezigheid, content: content, trigger: trigger)
and bezigheid is something that is different in every single cell. Tested it and now I get 2 different notifications!

Related

UNNotificationResponse mutableCopy attachment invalid

I have a local notification working fine and it delivers notifications with a content attachment using a url referencing an image in the app bundle. That works fine.
The issue I have is when I have an action that reissues the notification some time later.
Within the delegate function for Notification Center (didReceive response), I make a mutable copy of the response content and create a new tigger before creating a new request like this snippet shows.
let content = response.notification.request.content
let newContent = content.mutableCopy() as! UNMutableNotificationContent
// If I uncomment this next line, the notification gets added but without the attachment
// newContent.attachments = []
let newTrigger = UNTimeIntervalNotificationTrigger(timeInterval: snooozeInterval, repeats: false)
let request = UNNotificationRequest(identifier: response.notification.request.identifier,
content: newContent,
trigger: newTrigger)
do {
try await UNUserNotificationCenter.current().add(request)
} catch {
print(error)
}
When I do this, I get the following error:
Error Domain=UNErrorDomain Code=100 "Invalid attachment file URL" UserInfo={NSLocalizedDescription=Invalid attachment file URL}
if, before forming the request, I replace the newContent.attachments with no attachments, the request is formed OK and I get no error and the request is added. However, obviously, no attachment.
Is there a way to get a properly formed attachment so that I an add it and reissue with with the new request.

SwiftUI - Local Notifications identifier with multiples Core Data entities

I have multiple Core Data entities, one for each day of the week, and each time I add a new Item inside one of these I want to trigger a Local Notification for that specific Item. Since I can add the same Item in more than one entity, how can I set a unique Identifier for each one of them?
I was using the title of that item as an Identifier because they're all different but if I add the same title in two entities then it will display a unique notification of the last item added because it will replace the old one and what I want is to have different notifications with the same item in different entities.
This is my actual code of the Local Notification
let content = UNMutableNotificationContent()
content.title = self.items.itemsData[item].title
content.body = "Notification"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.weekday = 2
dateComponents.hour = 8
dateComponents.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: self.items.itemsData[item].title, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
Instead of using self.items.itemsData[item].title which is the same every time a new UNNotificationRequest is created for a particular item use UUID().uuidString which creates a new unique identifier each time it is called. You could probably use this unique identifier in combination with the title if that is more accurate for your scenario.
let request = UNNotificationRequest(identifier: self.items.itemsData[item].title + UUID().uuidString, content: content, trigger: trigger)

Reoccurring local notification for UTC time

I looked all over stack overflow and was only able to find reoccurring local notifications for a specific time. However, I am trying to find information on how to make a reoccurring local notification based off a UTC time. The reason behind when you set up a reoccurring notification, it will stay to that specific time.
For example, at the moment 00:00:00 UTC is 5pm eastern time but when day light savings hits in a few months, the new time will be 4pm. However, the reoccurring notification is still set to 5pm. So this notification is now one hour off because of day light savings.
I am trying to figure out how to accomplish this, so the local notification will move properly with day light savings. I am not sure if this is possible since the reoccurring is set to a specific time, but I would love to find more information on this.
By default current Time Zone is considered for delivering local notifications. To use UTC time while registering for local notification, you need to set Time Zone to UTC.
import UIKit
import UserNotifications
//get the notification center
let center = UNUserNotificationCenter.current()
//create the content for the notification
let content = UNMutableNotificationContent()
content.title = " Title"
content.subtitle = "SubTitle"
content.body = "jvsvsvasvbasbvfasfv"
content.sound = UNNotificationSound.default
var dateComp = DateComponents()
dateComp.timeZone = TimeZone(identifier: "UTC") // set time zone to UTC
dateComp.day = 1;
dateComp.hour = 08;
dateComp.minute = 00;
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComp, repeats: true)
//create request to display
let request = UNNotificationRequest(identifier: "ContentIdentifier", content: content, trigger: trigger)
//add request to notification center
center.add(request) { (error) in
if error != nil {
print("error \(String(describing: error))")
}
}
Above code sets notification every morning 8 am UTC time.

Repeat Local Notification at a specific time and after same time at intervals

It could be duplicate of Question asked - Repeating local notification daily at a set time with swift
But UILocalNotifications are deprecated iOS 10
I am working on alarm app, I need 2 things
1. local notification on a time
2. Repeat after a time interval
/// Code used to set notification
let content = UNMutableNotificationContent()
content.body = NSString.localizedUserNotificationString(forKey: titleOfNotification, arguments: nil)
content.userInfo=[]
Code That work fine hit notification at exact time
/* ---> Working Fine --> how i can repeat this after 60 second if untouched
let triggerDaily = Calendar.current.dateComponents([.hour,.minute,], from: dates)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: weekdays.isEmpty == true ? false : true)
*/
/// ---> Making it Repeat After Time - How Time is passed here ?
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 60, repeats: true)
/// ---> Adding Request
let request = UNNotificationRequest(identifier:dateOfNotification, content: content, trigger: trigger) UNUserNotificationCenter.current().add(request){(error) in
if (error != nil){
print(error?.localizedDescription ?? "Nahi pta")
} else {
semaphore.signal()
print("Successfully Done")
}
}
How I can achieve both things at same time ?
You can use UNUserNotificationCenter for local notifications, meanwhile, for the repeating notification you can use the performFetchWithCompletionHandler method, for this method you have to set the minimum time interval for the method to be called.
Please follow the link for more details -
https://developer.apple.com/documentation/uikit/core_app/managing_your_app_s_life_cycle/preparing_your_app_to_run_in_the_background/updating_your_app_with_background_app_refresh
ALSO Sample code -
func scheduleLocalNotification(subtitle: String, description: String, offerID: String) {
// Create Notification Content
let notificationContent = UNMutableNotificationContent()
// Configure Notification Content
notificationContent.title = "New lead for " + subtitle
notificationContent.body = description
notificationContent.userInfo = ["aps":
["alert": [
"title": subtitle,
"body": description,
"content-available": "1"
],
"ofrid": offerID,
"type": "BLBGSync",
"landinguri": "abc.com",
]
]
// Create Notification Request
let triggertime = UNTimeIntervalNotificationTrigger(timeInterval: 3600, repeats: false)
let notificationRequest = UNNotificationRequest(identifier: "YOUR_IDENTIFIER", content: notificationContent, trigger: triggertime)
// Add Request to User Notification Center
UNUserNotificationCenter.current().add(notificationRequest) { (error) in
if let error = error {
print("Unable to Add Notification Request (\(error), \(error.localizedDescription))")
}
}
}

Notification Center and changing timezones

Swift 4 & >iOS 10.0
I want to schedule a local notification at a certain date and at a given time (let's say 3PM). I want the notifications to always be fired at 3PM, whatever the timezone I am in (automatic rescheduling of notifications according to timezones).
Previously, you could tweak UILocalNotifications' time zone to achieve exactly this, like perfectly explained in this SO post. However, in >iOS 10.0, UILocalNotifications is deprecated.
Here is my code:
func scheduleNotification(title: String, message: String, atDate: Date){
let center = UNUserNotificationCenter.current()
// Create content
let content = UNMutableNotificationContent()
content.title = title
content.body = message
content.sound = UNNotificationSound.default()
// Create trigger
let calendar = Calendar(identifier: .gregorian)
let triggerDate = calendar.dateComponents([.year,.month,.day,.hour,.minute,.second,], from: atDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: false)
// Create identifier
let identifier = "\(UUID())"
// Create request & add to center
let request = UNNotificationRequest(identifier: identifier,
content: content,
trigger: trigger)
center.add(request, withCompletionHandler: { (error) in
})
}
Question:
How do you make the notification triggers properly with changing timezones ?
So, I managed to make it work. The triggerDate has a timeZone variable which is automatically nil, exactly like UILocalNotification.
triggerDate.timeZone behaves exactly like UILocalNotification.timeZone (behaviour described in this post, the same as mentioned in the question).
One of the reason it did not seem to work on the simulator was because I was not restarting the simulator when changing the timezone. Restarting will make everything work as expected.
Nota bene: Maybe a restart is not mandatory but since it's not obvious how much time a running simulator will take to detect the new timezone, I think restarting it is the most efficient solution.