Home > Software design >  Why the following demo sample of using UNUserNotificationCenter UNCalendarNotificationTrigger isn&
Why the following demo sample of using UNUserNotificationCenter UNCalendarNotificationTrigger isn&

Time:12-10

I was reading on how to show a local notification without Internet connection.

https://developer.apple.com/documentation/usernotifications/scheduling_a_notification_locally_from_your_app

I write a very simple demo test code, to show notification in next minute, by using UNUserNotificationCenter and UNCalendarNotificationTrigger.

However, when after the scheduled time hitted, nothing is pop up, doesn't matter when the app is foreground visible, or "minimize" to background.

Sample code

import UIKit

struct LocalDate {
    let year: Int
    let month: Int
    let day: Int
}

struct LocalTime {
    let hour: Int
    let minute: Int
}

extension Date {
    var localDate: LocalDate {
        let current = Calendar.current
        let components = current.dateComponents([.year, .month, .day], from: self)
        let year = components.year!
        let month = components.month!
        let day = components.day!
        return LocalDate(year: year, month: month, day: day)
    }
    
    var localTime: LocalTime {
        let current = Calendar.current
        let components = current.dateComponents([.hour, .minute], from: self)
        let hour = components.hour!
        let minute = components.minute!
        return LocalTime(hour: hour, minute: minute)
    }
    
    func adding(_ component: Calendar.Component, _ value: Int) -> Date {
        return Calendar.current.date(byAdding: component, value: value, to: self)!
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func clicked(_ sender: Any) {
        // Compute local date and local time for the next minute.
        let date = Date()
        let nextMinuteDate = date.adding(.minute, 1)
        let nextMinuteLocalDate = nextMinuteDate.localDate
        let nextMinuteLocalTime = nextMinuteDate.localTime
        
        //
        // STEP 1 : Create the Notification's Content
        //
        let content = UNMutableNotificationContent()
        content.title = "Title \(nextMinuteDate.localDate)"
        content.body = "Body \(nextMinuteDate.localTime)"
        
        print("\(content.title)")
        print("\(content.body)")
        
        //
        // STEP 2 : Specify the Conditions for Delivery
        //
        var dateComponents = DateComponents()
        dateComponents.calendar = Calendar.current

        dateComponents.year = nextMinuteLocalDate.year
        dateComponents.month = nextMinuteLocalDate.month
        dateComponents.day = nextMinuteLocalDate.day

        dateComponents.hour = nextMinuteLocalTime.hour
        dateComponents.minute = nextMinuteLocalTime.minute
        // Note: With or without the following code line, still doesn't work.
        //dateComponents.second = 0
        
        let trigger = UNCalendarNotificationTrigger(
                 dateMatching: dateComponents,
                 repeats: false
        )
        
        //
        // STEP 3 : Create and Register a Notification Request
        //
        // Create the request
        let uuidString = UUID().uuidString
        let request = UNNotificationRequest(identifier: uuidString,
                    content: content, trigger: trigger)

        // Schedule the request with the system.
        let notificationCenter = UNUserNotificationCenter.current()
        notificationCenter.add(request) { (error) in
           if error != nil {
               // Handle any errors.
               print("error \(error)")
           }
        }
        
        print("ok")
    }
    
}

Does anyone know why it is so? Is there anything I have missed out? Thanks.

CodePudding user response:

Everything you did is completely Ok you just need to add some code for Authorization and registration for all kinds of notifications by doing the following (basically to show the notifications):

extension AppDelegate {
    
    func registerNotification(block: ((_ status: Bool, _ error: Error?)-> ())? = nil) {
        let center = UNUserNotificationCenter.current()
        center.delegate = self
        let options: UNAuthorizationOptions = [.badge, .sound, .alert]
        center.requestAuthorization(options: options) { (flag, error) in
            if flag == true {
                /// Registering user notification
                DispatchQueue.main.async {
                    UIApplication.shared.registerForRemoteNotifications()
                }
            } else {
                print(error?.localizedDescription as Any)
            }
            block?(flag, error)
        }
    }
    
    func unRegisterNotification() {
        UIApplication.shared.unregisterForRemoteNotifications()
    }
    
}
// MARK:- UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo
        print("This is payload information: \(userInfo)")
        completionHandler([.badge,.alert,.sound])
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        
    }
}

Use the above code in your project and then use the following line of code in your AppDelegate's didFinishLaunchingWithOptions method:

registerNotification()
  • Related