2

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()
    }
}
E_net4
  • 27,810
  • 13
  • 101
  • 139
  • https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate – lorem ipsum Aug 15 '21 at 14:00
  • 1
    Does this answer your question? [Schedule local notification every n days (timezone safe)](https://stackoverflow.com/questions/67675639/schedule-local-notification-every-n-days-timezone-safe) – lorem ipsum Aug 15 '21 at 14:03
  • @loremipsum i want to repeat every single day not every x days – Isam Al Zareer Aug 16 '21 at 03:32
  • So, x = 1? The links are more about the setup of the notifications. You are missing key parts such as the delegate and telling your app what to do with the notification, go over both links. – lorem ipsum Aug 16 '21 at 06:56
  • @loremipsum I am new to coding and I don't understand a thing from the every n days – Isam Al Zareer Aug 16 '21 at 11:14
  • I can’t help you understand. All I can say is that your code is incomplete. You have to have a notification delegate, you have to tell your app what to do when a notification is posted when it is active and you have to tell your app where the notification delegate is in the AppDelegate. The SO question has a decent example on how to start the setup, the documentation has in a big yellow box the information on where to initialize the NotificationManager in the AppDelegate. The n days part is not that important the setup is what is important. – lorem ipsum Aug 16 '21 at 11:52
  • Oh, and maybe the most important part is that the `Button` `action` is for calling methods not making them – lorem ipsum Aug 16 '21 at 12:02
  • Did you figure it out? – lorem ipsum Aug 17 '21 at 10:33
  • 1
    If my code answered your question please accept and maybe upvote – lorem ipsum Aug 17 '21 at 23:40

3 Answers3

3

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()
    }
}
lorem ipsum
  • 21,175
  • 5
  • 24
  • 48
1

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()
    }
}
  • Just FYI using static calls repeatedly is considered bad practice. That is why I have the variable at the top and added the notificationCenter variable in the manager. – lorem ipsum Aug 17 '21 at 23:39
  • This doesn't work anymore, I think there is a problem with the API and Apple broke the notifications. Test it and let me know if you get it to work but I couldn't with a blank project – Arturo Feb 17 '22 at 16:28
  • i gave up earlier on notifications – Isam Al Zareer May 06 '22 at 13:44
0

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
Truptika
  • 41
  • 4