I made this simple code to try how Local Notifications works with Core Data and the main problem is that, after adding a Data Core item, I can receive my notification after 60 seconds but if I remove it I still receive it. Is there a function that I can call to delete that specific notification when I call my deleteItem function?
Another question that I have is how can I set a day of the week and timing to trigger that notification and not repeating after few seconds?
ContentView:
import UserNotifications
import SwiftUI
import CoreData
struct ContentView: View {
//Core Data
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(entity: Notifications.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Notifications.date, ascending: false)]) var notifications: FetchedResults<Notifications>
var titles = ["Hello", "Weekend", "Streaming", "ScoobyDoo"]
var subtitles = ["Hello2", "Weekend2", "Streaming2", "ScoobyDoo2"]
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: FavoriteView()) {
Text("Favorite View")
}
List {
ForEach(0 ..< titles.count) {title in
HStack {
Text(self.titles[title])
Image(systemName: "heart")
.onTapGesture {
if self.checkItem(title: self.titles[title]) {
do {
try self.deleteItem(title: self.titles[title])
print("title deleted")
} catch {
print(error)
}
} else {
self.addItem(item: self.titles[title])
print("item added")
// Notification content
let content = UNMutableNotificationContent()
content.title = self.titles[title]
content.subtitle = self.subtitles[title]
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
}
}
}
}
Button("Request Authorization") {
// Ask for notification when app launches
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
if success {
print("All set")
} else if let error = error {
print(error.localizedDescription)
}
}
}
Button("Remove Notifications") {
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
print("Removed")
}
}
}
}
private func checkItem(title: String) -> Bool {
let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Notifications")
request.predicate = NSPredicate(format: "title == %@", title)
request.fetchLimit = 1
var trueFalse = true
do {
let count = try managedObjectContext.count(for: request)
if count == 0 {
trueFalse = false
} else {
trueFalse = true
}
} catch {
print(error)
}
return trueFalse
}
private func deleteItem(title: String) throws {
let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Notifications")
request.predicate = NSPredicate(format: "title == %@", title)
try managedObjectContext.execute(NSBatchDeleteRequest(fetchRequest: request))
saveFavorites()
}
func addItem(item: String) {
let newItem = Notifications(context: managedObjectContext)
newItem.title = item
saveFavorites()
}
func saveFavorites() {
do {
try managedObjectContext.save()
} catch {
print(error)
}
}
}
FavoriteView:
import SwiftUI
import CoreData
struct FavoriteView: View {
//Core Data
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(entity: Notifications.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Notifications.date, ascending: false)]) var notifications: FetchedResults<Notifications>
var body: some View {
List {
ForEach(notifications, id: \.self) { item in
Text(item.title)
}
}
}
}
Modify the core data model to include the notification identifier that you're providing while adding the request. And then while removing the notification from core data you can use this identifier to remove the local notification like this:
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [identifier])
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [identifier])