My problem is that I am trying to schedule notifications that come daily at a specific time this is my code
import SwiftUI
struct notifView: View {
var body: some View {
VStack {
VStack {
Button("Request Permission") {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
print("Access Granted!")
} else {
print("Access Not Granted")
}
}
}
.frame(width: 200, height: 60, alignment: .center)
.foregroundColor(.black)
.background(Color.blue)
.cornerRadius(10.0)
.padding()
Button("Add Notifications For Morning") {
func scheduleNotification() {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Morning Time"
content.body = "Wake Up And Be Productive!"
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.hour = 6
dateComponents.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
}
.padding()
Button("Add Notifications For Middle Of The Day") {
func scheduleNotification() {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Middle Of The Day"
content.body = "Did you have your daily run?"
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.hour = 12
dateComponents.minute = 30
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
}
.padding()
Button("Add Notifications For Night") {
func scheduleNotification() {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Night Time"
content.body = "Time to sleep"
content.categoryIdentifier = "reminder"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.hour = 20
dateComponents.minute = 51
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
}
.foregroundColor(.blue)
.padding()
}
}
}
}
struct notifView_Previews: PreviewProvider {
static var previews: some View {
notifView()
}
}
Look at the comments within the code
import SwiftUI
//struct and class should start with an uppercase
struct NotificationView: View {
//Central location for Notification code including the delegate
// A call to the notificationManager just like the line of code below has to be included in
// application(_:willFinishLaunchingWithOptions:) or
// application(_:didFinishLaunchingWithOptions:)
//https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate
//https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-an-appdelegate-to-a-swiftui-app
let notificationManager: NotificationManager = NotificationManager.shared
var body: some View {
VStack {
VStack {
Button("Request Permission") {
//Call a func here don't define it
notificationManager.requestAuthorization()
}
.frame(width: 200, height: 60, alignment: .center)
.foregroundColor(.black)
.background(Color.blue)
.cornerRadius(10.0)
.padding()
Button("Add Notifications For Morning") {
//Unique date components
var dateComponents = DateComponents()
dateComponents.hour = 6
dateComponents.minute = 30
//Reusable method
self.notificationManager.scheduleTriggerNotification(title: "Morning Time", body: "Wake Up And Be Productive!", categoryIdentifier: "reminder", dateComponents: dateComponents, repeats: true)
}
.padding()
Button("Add Notifications For Middle Of The Day") {
var dateComponents = DateComponents()
dateComponents.hour = 12
dateComponents.minute = 30
//Reusable method
self.notificationManager.scheduleTriggerNotification(title: "Middle Of The Day", body: "Did you have your daily run?", categoryIdentifier: "reminder", dateComponents: dateComponents, repeats: true)
}
.padding()
Button("Add Notifications For Night") {
var dateComponents = DateComponents()
dateComponents.hour = 20
dateComponents.minute = 51
//Reusable method
self.notificationManager.scheduleTriggerNotification(title: "Night Time", body: "Time to sleep", categoryIdentifier: "reminder", dateComponents: dateComponents, repeats: true)
}
.foregroundColor(.blue)
.padding()
Button("Print Notifications") {
//Reusable method
self.notificationManager.printNotifications()
}
.foregroundColor(.blue)
.padding()
Button("Delete Notifications") {
//Reusable method
self.notificationManager.deleteNotifications()
}
.foregroundColor(.blue)
.padding()
}
}
}
}
//You need a central location for the notification code because
// it is needed in more than 1 spot. At launch in the AppDelegate
// and wherever you schedule your notifications
class NotificationManager: NSObject, UNUserNotificationCenterDelegate{
//Singleton is requierd because of delegate
static let shared: NotificationManager = NotificationManager()
let notificationCenter = UNUserNotificationCenter.current()
private override init(){
super.init()
//This assigns the delegate
notificationCenter.delegate = self
}
func requestAuthorization() {
print(#function)
notificationCenter.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
print("Access Granted!")
} else {
print("Access Not Granted")
}
}
}
func deleteNotifications(){
print(#function)
notificationCenter.removeAllPendingNotificationRequests()
}
///This is just a reusable form of all the copy and paste you did in your buttons. If you have to copy and paste make it reusable.
func scheduleTriggerNotification(title: String, body: String, categoryIdentifier: String, dateComponents : DateComponents, repeats: Bool) {
print(#function)
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.categoryIdentifier = categoryIdentifier
content.sound = UNNotificationSound.default
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: repeats)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
notificationCenter.add(request)
}
///Prints to console schduled notifications
func printNotifications(){
print(#function)
notificationCenter.getPendingNotificationRequests { request in
for req in request{
if req.trigger is UNCalendarNotificationTrigger{
print((req.trigger as! UNCalendarNotificationTrigger).nextTriggerDate()?.description ?? "invalid next trigger date")
}
}
}
}
//MARK: UNUserNotificationCenterDelegate
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(.banner)
}
}
struct NotificationView_Previews: PreviewProvider {
static var previews: some View {
NotificationView()
}
}
I got it working with the help of this video:
https://www.youtube.com/watch?v=mG9BVAs8AIo
and some code from #lorem ipsum thank you so much for the help
import SwiftUI
import UserNotifications
struct notifView: View {
var body: some View {
VStack {
Button("Request Permission") {
NotificationManager.instance.requestAuthorization()
}
.padding()
.background(Color.green)
.cornerRadius(10)
Button("1st Notification") {
var dateComponents = DateComponents()
dateComponents.hour = 4
dateComponents.minute = 01
// reusable code thanks to lorem ipsum
NotificationManager.instance.scheduleTriggerNotification(title: "1st Notification", body: "1st Notification Body", categoryIdentifier: UUID().uuidString, dateComponents: dateComponents, repeats: true)
}
.padding()
.background(Color.yellow)
.cornerRadius(10)
Button("2nd Notification") {
var dateComponents = DateComponents()
dateComponents.hour = 5
dateComponents.minute = 40
// reusable code thanks to lorem ipsum
NotificationManager.instance.scheduleTriggerNotification(title: "2nd Notification", body: "2nd Notification Body", categoryIdentifier: UUID().uuidString, dateComponents: dateComponents, repeats: true)
}
.padding()
.background(Color.yellow)
.cornerRadius(10)
Button("3rd Notification") {
var dateComponents = DateComponents()
dateComponents.hour = 12
dateComponents.minute = 10
// reusable code thanks to lorem ipsum
NotificationManager.instance.scheduleTriggerNotification(title: "3rd Notification", body: "3rd Notification Body", categoryIdentifier: UUID().uuidString, dateComponents: dateComponents, repeats: true)
}
.padding()
.background(Color.yellow)
.cornerRadius(10)
}
}
}
class NotificationManager {
static let instance = NotificationManager()
func requestAuthorization() {
let options: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: options) { (success, error) in
if let error = error {
print("ERROR: \(error)")
} else {
print("SUCCESS")
}
}
}
// reusable code thanks to lorem ipsum
func scheduleTriggerNotification(title: String, body: String, categoryIdentifier: String, dateComponents : DateComponents, repeats: Bool) {
print(#function)
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.categoryIdentifier = categoryIdentifier
content.sound = UNNotificationSound.default
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: repeats)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
notifView()
}
}
Add one day in today's date so we got next day and then add your specific time on which you want trigger the notification.
var triggerComponents = DateComponents()
let nextDay = Calendar.current.date(byAdding: .day, value: 1, to: Date()) ?? Date()
triggerComponents = Calendar.current.dateComponents([.year, .month, .day, .hour], from: nextDay)
triggerComponents.hour = 14
Related
I have local notifcations working in my Apple Watch app. Setting the interval in houser and the save buttonis also working. The only thing that is not working is displaying a random message. It selects one of the three from the randomText() function and then one is repeated every "interval" time...
This is one file.
import SwiftUI
import UserNotifications
struct Nottie2: View {
#AppStorage("notificationInterval") var notificationInterval: Int = 1
#AppStorage("isSnoozed") var isSnoozed: Bool = false
#AppStorage("isNotificationsEnabled") var isNotificationsEnabled: Bool = false
#State private var borderColor = Color.orange
#State private var buttonText = "Save"
var body: some View {
VStack {
Toggle(isOn: $isNotificationsEnabled) {
if isNotificationsEnabled {
Text("Turn off")
}else {
Text("Turn on")
}
}
.padding()
.onChange(of: isNotificationsEnabled) { enabled in
if enabled {
requestPermission()
} else {
disableNotification()
}
}
if isNotificationsEnabled {
Picker("Notification Interval", selection: $notificationInterval) {
ForEach(1...6, id: \.self) { interval in
Text("\(interval) hour\(interval > 1 ? "s" : "")")
}
}.frame(height: 60)
.padding()
Button(action: {
enableNotification()
self.buttonText = "Saving"
self.borderColor = .green
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.buttonText = "Saved"
self.borderColor = .green
}
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
self.buttonText = "Save"
self.borderColor = .orange
}
})
{
Text(buttonText)
}.foregroundColor(.white)
.padding(1)
.frame(width: 75)
.padding(7)
.overlay(
RoundedRectangle(cornerRadius: 25)
.stroke(borderColor, lineWidth: 2))
.buttonStyle(.plain)
}
}
.onAppear() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if granted {
print("Permission granted")
} else {
print("Permission denied")
isNotificationsEnabled = false
}
}
}
.onReceive(NotificationCenter.default.publisher(for: WKExtension.applicationDidBecomeActiveNotification)) { _ in
if isSnoozed {
enableNotification(snooze: true)
}
}
}
function to request the notification permissions
private func requestPermission() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if granted {
print("Permission granted")
enableNotification()
} else {
print("Permission denied")
isNotificationsEnabled = false
}
}
}
randomText() is called. I think that the issue is somewhere here. I think it (I do not know how) clear the notification after it is dismissed
private func enableNotification(snooze: Bool = false) {
let content = UNMutableNotificationContent()
// content.title = "Notification Title"
content.body = randomText()
content.sound = UNNotificationSound.default
var trigger: UNNotificationTrigger
if snooze {
trigger = UNTimeIntervalNotificationTrigger(timeInterval: 540, repeats: false)
} else {
trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval(notificationInterval * 3600), repeats: true)
}
let request = UNNotificationRequest(identifier: "notification", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
Function with an small array with random notifications texts.
func randomText() -> String {
let words = ["Place", "Cat", "House"]
return words[Int(arc4random_uniform(UInt32(words.count)))]
}
Rest of the notification actions.
private func disableNotification() {
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["notification"])
}
private func snoozeNotification() {
isSnoozed = true
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["notification"])
enableNotification(snooze: true)
}
private func dismissNotification() {
isSnoozed = false
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["notification"])
}
private func showNotificationActions() {
let snoozeAction = UNNotificationAction(identifier: "snooze", title: "Snooze", options: [])
let dismissAction = UNNotificationAction(identifier: "dismiss", title: "Dismiss", options: [.destructive])
let category = UNNotificationCategory(identifier: "notificationActions", actions: [snoozeAction, dismissAction], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
}
}
struct Nottie2_Previews: PreviewProvider {
static var previews: some View {
Nottie2()
}
}
This code works:
import SwiftUI
import UserNotifications
struct NotifyView: View {
#AppStorage("isNotificationsEnabled") var isNotificationsEnabled: Bool = false
#State private var interval = 1
#State private var buttonText = "Save"
#State private var borderColor = Color.orange
let messages = [
"Take a 5 minute walk.",
"Drink a glass of water.",
"Stretch your legs.",
"Take deep breaths.",
"Close your eyes and meditate for a minute.",
"Do a few jumping jacks.",
"Think of something you're grateful for.",
"Write down your thoughts in a journal.",
"Read a book for 5 minutes.",
"Call a friend and say hello.",
"Smile and relax your shoulders.",
"Make a cup of tea and take a break.",
]
var body: some View {
VStack {
Text("Notifications:")
.foregroundColor(.orange)
.fontWeight(.semibold)
Toggle(isOn: $isNotificationsEnabled) {
if isNotificationsEnabled {
Text("Turn off")
}else {
Text("Turn on")
}
}
.padding()
if isNotificationsEnabled {
Picker("Interval (hours)", selection: $interval) {
ForEach(1...10, id: \.self) { i in
Text("\(i) hours")
}
}
.pickerStyle(.wheel)
.padding()
.frame(height: 70)
Button(action: {
scheduleNotifications()
self.buttonText = "Saving"
self.borderColor = .green
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.buttonText = "Saved"
self.borderColor = .green
}
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
self.buttonText = "Save"
self.borderColor = .orange
}
})
{
Text(buttonText)
}
.foregroundColor(.white)
.padding(1)
.frame(width: 75)
.padding(7)
.overlay(
RoundedRectangle(cornerRadius: 25)
.stroke(borderColor, lineWidth: 2))
.buttonStyle(.plain)
}
}
}
func scheduleNotifications() {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) { granted, error in
if let error = error {
print(error.localizedDescription)
}
}
center.removeAllPendingNotificationRequests()
for i in 1...10 {
let randomIndex = Int.random(in: 0..<messages.count)
let message = messages[randomIndex]
let content = UNMutableNotificationContent()
content.title = "Time to take a break!"
content.body = message
content.sound = UNNotificationSound.default
content.categoryIdentifier = "reminder"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval(i * interval * 3600), repeats: false)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request) { error in
if let error = error {
print(error.localizedDescription)
}
}
}
}
}
struct NotifyView_Previews: PreviewProvider {
static var previews: some View {
NotifyView()
}
}
I have this code that should send a notification to the user on the same day every month. However I'm can't simulate this, so I can't test it. I was wondering if any of you could proof check it, to ensure it does send a notification every month.
Thanks
static func addNotification(){
let center = UNUserNotificationCenter.current()
let addRequest = {
let content = UNMutableNotificationContent()
content.title = "Test"
content.subtitle = "Test"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.day = 31
dateComponents.hour = 12
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: "", content: content, trigger: trigger)
center.add(request)
}
center.getNotificationSettings { settings in
if settings.authorizationStatus == .authorized{
addRequest()
}
else{
center.requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
if success{
addRequest()
}
}
}
}
}
Example (I try to create something like this.
Now u can see, here you may choose time and interval)
I created reminder, where a user can choose how often to receive notifications (every 2 days, every 3 days etc.), but I also want the user to be able to choose the time. I know how to create reminder which will send notifications at the selected time, but I have to use UNCalendarNotificationTrigger, and problem is that I use UNTimeIntervalNotificationTrigger. Thank you
#IBOutlet weak var picker: UIPickerView!
#IBOutlet weak var timePicker: UIDatePicker!
#IBAction func setReminderBtnTapped(_ sender: Any) {
let content = UNMutableNotificationContent()
content.title = "Test"
content.body = "Blablabla"
content.sound = .default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval((picker.selectedRow(inComponent: 1)+1)*(24*3600)), repeats: true)
let request = UNNotificationRequest(identifier: "blabla.reminder", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
if let error = error {
print("error")
}
}
print("Notification added")
}
try this code:
private func setLocalNotification(hour: Int, minute: Int, completionHandler: #escaping (Bool) -> Void) {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { [weak self] (granted, error) in
guard let self = self else {
return
}
let center = UNUserNotificationCenter.current()
center.removeAllPendingNotificationRequests()
guard error == nil else {
completionHandler(false)
return
}
if granted {
let content = UNMutableNotificationContent()
content.title = "title"
content.sound = UNNotificationSound.default
content.badge = 1
var dateComponents = DateComponents()
dateComponents.hour = hour
dateComponents.minute = minute
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
completionHandler(true)
return
}
completionHandler(false)
}
}
and you can call by get date from datePicker like this:
let date = self.timepPicker.date
let calendar = Calendar.current
let hour = calendar.component(.hour, from: date) // get hour
let minutes = calendar.component(.minute, from: date) // get minute
self.setLocalNotification(hour: hour, minute: minutes) { [weak self] isSet in
guard let self = self else {
return
}
if !isSet {
let center = UNUserNotificationCenter.current()
center.removeAllPendingNotificationRequests() // remove previus notification
}
}
update answer for
repeat X time in every n day:
create extension from date for create simple date getDateComponents:
extension Date {
public func getDateComponents() -> DateComponents {
let dateComponents = Calendar.current.dateComponents([.hour, .minute, .second, .day], from: self)
return dateComponents
}
}
and update setLocalNotification function:
private func setLocalNotification(repeatCount: Int, jumpNextDay: Int, hour: Int, minute: Int) {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
let center = UNUserNotificationCenter.current()
center.removeAllPendingNotificationRequests()
guard error == nil else {
return
}
if granted {
let content = UNMutableNotificationContent()
content.title = "title"
content.sound = UNNotificationSound.default
content.badge = 1
// create date from hour and minute based on current
let firstDate = Calendar.current.date(bySettingHour: hour, minute: minute, second: 0, of: Date())!
let firstTimeInterval = firstDate.timeIntervalSince1970 // get timeInterval
// example run for
// repeat count 5 and jump 2
// 2 4 6 8 10
for i in stride(from: jumpNextDay, to: jumpNextDay * (repeatCount + 1), by: jumpNextDay) {
// create next day
// 86400 next time interval added to first time interval
// create time interval from first date
// 2 next day = firstTimeInterval + 2 * 86400
let timeIntervalForTrigger = firstTimeInterval + Double((i * 86400))
// create date from time interval
let date = Date.init(timeIntervalSince1970: timeIntervalForTrigger)
// create datecomponnet
let dateComponents = date.getDateComponents()
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request)
}
}
}
}
and call:
let date = self.timepPicker.date
let calendar = Calendar.current
let hour = calendar.component(.hour, from: date) // get hour
let minutes = calendar.component(.minute, from: date) // get minute
self.setLocalNotification(repeatCount: 2, jumpNextDay: 2, hour: hour, minute: minutes)
I would like to schedule a local notification from iOS14 widget.
How can I do it?
I tried implementing the following:
let center = UNUserNotificationCenter.current()
center.delegate = self
let content = UNMutableNotificationContent()
content.title = "Some Title"
content.body = "Some Body"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString,
content: content, trigger: trigger)
center.add(request) { (error) in
if error != nil {
// Handle any errors.
}
I did with this.
func createDate(day: Int, month : Int, hour: Int, minute: Int, year: Int)->Date{
var components = DateComponents()
components.hour = hour
components.minute = minute
components.year = year
components.day = day
components.month = month
components.timeZone = .current
let calendar = Calendar(identifier: .gregorian)
return calendar.date(from: components)!
}
// 📢///CreateNitification
func scheduleNotification(at date: Date, identifierUnic : String, body: String, titles:String) {
let triggerWeekly = Calendar.current.dateComponents([.day, .month, .hour,.minute, .year], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerWeekly, repeats: true)
let content = UNMutableNotificationContent()
content.title = titles
content.body = body
content.sound = UNNotificationSound.default
content.categoryIdentifier = "todoList2"
let request = UNNotificationRequest(identifier: identifierUnic, content: content, trigger: trigger)
// UNUserNotificationCenter.current().delegate = self
/// UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ["textNotification2"])
/// UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print(" We had an error: \(error)")
}}
}
// Call
func callNotifications(){
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
let adte = createDate(day: 3, month: 6, hour: 16, minute: 51, year: 2021)
scheduleNotification(at: adte, identifierUnic: UUID().uuidString, body: "Widgets on Work", titles: "check 123")
}
func getTimeline(in context: Context, completion: #escaping (Timeline<Entry>) -> ()) {
callNotifications()
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
Notification is working fine
but one thing is pending, how can I call UNUserNotificationCenter.current().delegate = self?
Thanks
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])