Home > database >  I want to create a notification that will be triggered when another notification is displayed in swi
I want to create a notification that will be triggered when another notification is displayed in swi

Time:09-08

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

CodePudding user response:

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)
 }

CodePudding user response:

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
        }
    }
}
  • Related