skip to Main Content

Basically, I have an application where the user can set the time of the first notification, and the following ones will happen repeatedly. For example, I want to be notified every 8 hours, but the first notification will not be from now on. So I need to create 2 notifications, one for the first one, and as soon as the first one goes off, I need to set a new notification every 8 hours.

A practical example: I will take my medicine at 8 o’clock in the morning, but now it’s 5 o’clock, and I want to be notified every 8 hours. The first alarm must be for 8 o’clock from 8 o’clock, that is, 4 o’clock. For that, I made a logic:

enter image description here

However, the other alarms cannot have the same time as the first one, because, as in the previous example, if I left the same trigger, the alarms would be 11 hours, not 8. I need the first to be 11 hours, and the subsequent numbers of 8 in the example.

I already have the code for the first alarm, however, I can’t think of a way to create the subsequent ones, which will keep repeating according to the desired time, for example, 8 in 8, 12 in 12

2

Answers


  1. Use a repeating UNCalendarNotificationTrigger for each separate time of day. In your case, that means use three triggers (and therefore three requests): one each at 8, 16, and 0 hours. You don’t need to add a separate request for the soonest occurrence.

    for i in 0 ..< 3 {
        let when = DateComponents(hour: (8 + 8 * i) % 24, minute: 0)
        let trigger = UNCalendarNotificationTrigger(dateMatching: when, repeats: true)
        let request = UNNotificationRequest(
            identifier: "trigger-(i)",
            content: someContent(),
            trigger: trigger
        )
        UNUserNotificationCenter.current().add(request) { error in
            if let error = error {
                // handle error
            }
        }
    }
    
    Login or Signup to reply.
  2. You need to setup a BGAppRefreshTask, which will tell the System to periodically wake your app to run in the Background to do something in about 30 seconds, then app is Suspended.
    You can set a Refreshing Task every 6 hours to check and make a new Local Push Notification if needed.

    Here is the guide: https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/using_background_tasks_to_update_your_app

    When you setup your local notification:

    // Create the request
    let uuidString = UUID().uuidString // SAVE this one to UserDefault then you can fetch delivered/pending notification if needed.
    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.
       }
    }
    

    Function in your AppDelegate.swift

    // Here you register it in didFinishLaunching()
    BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.apple-samplecode.ColorFeed.refresh", using: nil) { task in
         self.handleAppRefresh(task: task as! BGAppRefreshTask)
    }
    
    // Func to register a next background refresh task
    func scheduleAppRefresh() {
       let request = BGAppRefreshTaskRequest(identifier: "com.example.apple-samplecode.ColorFeed.refresh")
       // Fetch no earlier than 15 minutes from now.
       request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
            
       do {
          try BGTaskScheduler.shared.submit(request)
       } catch {
          print("Could not schedule app refresh: (error)")
       }
    }
    
    // Here is where you do your logic when the app runs by background refresh event.
    func handleAppRefresh(task: BGAppRefreshTask) {
       // Schedule a new refresh task.
       scheduleAppRefresh()
    
       // Create an operation that performs the main part of the background task.
       let operation = RefreshAppContentsOperation() // you dont really need this one, just call your logic here.
    
       // Ex:
       UNUserNotificationCenter.current().getDeliveredNotifications {[weak self] listNoti in
           for noti in listNoti {
               if noti.identifier == [your UUID that you just save in UserDefault before] {
                   // It delivered, now make new Local notification...
               }
           }
       }
       
       // Provide the background task with an expiration handler that cancels the operation.
       task.expirationHandler = {
          operation.cancel()
       }
    
    
       // Inform the system that the background task is complete
       // when the operation completes.
       operation.completionBlock = {
          task.setTaskCompleted(success: !operation.isCancelled)
       }
    
    
       // Start the operation.
       operationQueue.addOperation(operation)
     }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search