ios – Will a neighborhood push notification motion execute if chosen whereas an app will not be operating?


I take advantage of native push notifications to inform my customers when a session is able to start or finish. My app performs a number of duties when a session is began or ended. At present, the person has to launch the app to manually begin/finish a session. I wish to supply notification actions to begin/finish a session with out launching the app within the foreground.

When the app is operating within the background and I choose a notification motion, the UNUserNotificationCenterDelegate’s didReceive technique is named, I obtain a UNNotificationResponse, and my app performs the duties related to beginning/ending a session as anticipated.

Nonetheless, if I power shut my app from the App Switcher after which choose a notification motion when the notification is available in, it seems the didReceive delegate technique will not be being referred to as. My app does not run the duties wanted to begin/finish a session correctly.

Apple’s docs on Actionable Notifications states:
Actionable notifications let the person reply to a delivered notification with out launching the corresponding app. Different notifications show info in a notification interface, however the person’s solely plan of action is to launch the app. For an actionable notification, the system shows a number of buttons along with the notification interface. Tapping a button sends the chosen motion to the app, which then processes the motion within the background.

Am I doing one thing improper right here or maybe misunderstanding how notification actions work?

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    let injectionContainer = AppContainer()
    let dbMaintenanceManager = DBMaintenanceManager()
    var window: UIWindow?

    func software(_ software: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
        
        requestNotificationAuthorization()
        
        dbMaintenanceManager.performMaintenanceTasks()
        
        let look = UINavigationBarAppearance()
        look.backgroundColor = Shade.primaryBlue
        look.titleTextAttributes = [.foregroundColor: UIColor.white]
        
        UINavigationBar.look().standardAppearance = look
        UINavigationBar.look().scrollEdgeAppearance = look
        UINavigationBar.look().tintColor = .white
      
        let mainVC = injectionContainer.makeMainViewController()

        window = UIWindow(body: UIScreen.primary.bounds)
        window?.overrideUserInterfaceStyle = .gentle
        window?.makeKeyAndVisible()
        window?.rootViewController = mainVC

        return true
    }
        
    func applicationWillEnterForeground(_ software: UIApplication) {
        dbMaintenanceManager.performMaintenanceTasks()
    }
    
    non-public func requestNotificationAuthorization() {
        let notificationCenter = UNUserNotificationCenter.present()
        
        notificationCenter.requestAuthorization(choices: [.alert, .sound, .badge]) { granted, error in
            if let error = error {
                print("Error requesting authorization: (error)")
                return
            }

            if granted {
                let startAction = UNNotificationAction(identifier: "START_ACTION",
                                                              title: "Begin Session",
                                                       choices: [])
                
                let endAction = UNNotificationAction(identifier: "END_ACTION",
                                                            title: "Finish Session",
                                                     choices: [])
                
                let startCategory = UNNotificationCategory(identifier: "START_CATEGORY",
                                                                  actions: [startAction],
                                                                  intentIdentifiers: [],
                                                                  choices: [])
                
                let endCategory = UNNotificationCategory(identifier: "END_CATEGORY",
                                                                  actions: [endAction],
                                                                  intentIdentifiers: [],
                                                                  choices: [])
                
                let notificationCenter = UNUserNotificationCenter.present()
                notificationCenter.setNotificationCategories([startCategory, endCategory])
                notificationCenter.delegate = self
                print("Notification permission approved")
            } else {
                print("Notification permission denied")
            }
        }
    }
}

// MARK: - UNUserNotificationCenterDelegate

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ heart: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        NotificationCenter.default.put up(title: .didReceivePushNotification, object: notification)
        completionHandler([.banner, .list, .sound])
    }

    func userNotificationCenter(_ heart: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        handleNotificationResponse(response)
        completionHandler()
    }
        
    non-public func handleNotificationResponse(_ response: UNNotificationResponse) {
        let userInfo = response.notification.request.content material.userInfo
        guard let id = userInfo["sessionId"] as? String else {
            print("Error studying session id related to notification")
            return
        }

        change response.actionIdentifier {
        case "START_ACTION":
            NotificationCenter.default.put up(title: .didStartSession, object: nil, userInfo: ["sessionId" : id])
        case "END_ACTION":
            NotificationCenter.default.put up(title: .didEndSession, object: nil, userInfo: ["sessionId" : id])
        default:
            break
        }
    }
}

extension Notification.Identify {
    static let didReceivePushNotification = Notification.Identify("didReceivePushNotification")
    static let didStartSession = Notification.Identify("didStartSession")
    static let didEndSession = Notification.Identify("didEndSession")
}
class PushScheduler {
    
    enum NotificationType {
        case reminder
        case completion
    }
    
    let notificationCenter = UNUserNotificationCenter.present()
    
    func scheduleNotification(for session: Session, sort: NotificationType) {
        change session.sort {
        case .now:
            scheduleNowNotification(session: session, sort: sort)
        case .later:
            scheduleLaterNotification(session: session, sort: sort)
        case .recurring:
            scheduleRecurringNotification(session: session, sort: sort)
        case .none:
            break
        }
    }
    
    non-public func scheduleNowNotification(session: Session, sort: NotificationType) {
        if sort == .completion { scheduleCompletionNotification(session: session, date: session.endTime) }
    }
    
    non-public func scheduleLaterNotification(session: Session, sort: NotificationType) {
        if sort == .reminder { scheduleReminderNotification(session: session, date: session.startTime) }
        if sort == .completion { scheduleCompletionNotification(session: session, date: session.endTime) }
    }
    
    non-public func scheduleRecurringNotification(session: Session, sort: NotificationType) {
        for day in session.recurringDays {
            if sort == .reminder { scheduleReminderNotification(session: session, date: session.startTime, recurringDay: day) }
            if sort == .completion { scheduleCompletionNotification(session: session, date: session.endTime, recurringDay: day) }
        }
    }
    
    non-public func scheduleReminderNotification(session: Session, date: Date, recurringDay: Weekday? = nil) {
        let content material = UNMutableNotificationContent()
        content material.title = "Reminder"
        content material.physique = "Your session (session.title) is beginning."
        content material.sound = .default
        content material.categoryIdentifier = "START_CATEGORY"
        content material.userInfo = ["sessionId" : session._id.stringValue]
        
        let set off: UNNotificationTrigger
        if let recurringDay = recurringDay {
            set off = createWeeklyTrigger(date: date, weekday: recurringDay)
        } else {
            set off = createTrigger(date: date)
        }
        
        let request = UNNotificationRequest(identifier: "(session._id)-reminder", content material: content material, set off: set off)
        notificationCenter.add(request, withCompletionHandler: nil)
    }
    
    non-public func scheduleCompletionNotification(session: Session, date: Date, recurringDay: Weekday? = nil) {
        let content material = UNMutableNotificationContent()
        content material.title = "Session Full"
        content material.physique = "Your session (session.title) is full."
        content material.sound = .default
        content material.categoryIdentifier = "END_CATEGORY"
        content material.userInfo = ["sessionId" : session._id.stringValue]
        
        let set off: UNNotificationTrigger
        if let recurringDay = recurringDay {
            set off = createWeeklyTrigger(date: date, weekday: recurringDay)
        } else {
            set off = createTrigger(date: date)
        }
        
        let request = UNNotificationRequest(identifier: "(session._id)-completion", content material: content material, set off: set off)
        notificationCenter.add(request, withCompletionHandler: nil)
    }
    
    non-public func createTrigger(date: Date) -> UNCalendarNotificationTrigger {
        let calendar = Calendar.present
        let elements = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
        return UNCalendarNotificationTrigger(dateMatching: elements, repeats: false)
    }
    
    non-public func createWeeklyTrigger(date: Date, weekday: Weekday) -> UNCalendarNotificationTrigger {
        var elements = Calendar.present.dateComponents([.hour, .minute, .second], from: date)
        elements.weekday = weekday.rawValue
        return UNCalendarNotificationTrigger(dateMatching: elements, repeats: true)
    }
    
    func updateNotification(for session: Session) {
        // Take away present notifications for this session
        removeNotification(for: session._id)
        
        // Schedule new notifications
        if session.sort == .now {
            scheduleNotification(for: session, sort: .completion)
        } else {
            scheduleNotification(for: session, sort: .reminder)
        }
        
    }
    
    func removeNotification(for sessionId: ObjectId) {
        notificationCenter.removePendingNotificationRequests(withIdentifiers: ["(sessionId)-reminder"])
    }
}```

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles