Sync local notifications with CloudKit?

Viewed 379

I'm working on an app with CloudKit sync for its Core Data database right now. I want to add notifications to the app but am not sure the best way to go about getting notifications that will sync across devices. They will simply be timed notifications based on user-set due dates. Normally I would simply use UNUserNotificationCenter to create a UNNotificationRequest whenever a user sets a due date, but I want these notifications to sync across devices and I'm not sure exactly how to do that.

I know CloudKit can be used to send push notifications, but it doesn't seem like they're meant to be used on simple time triggers like this, are they?

The best idea I have right now is to listen for NSPersistentStoreRemoteChange and run through every single item, check to see if it has a notifications set on the device, and if not, to create one. That seems like a bit intensive of a task to be running every sync though.

1 Answers

You are correct that CloudKit notifications are designed to be fired when a CKRecord is created--not at specific times the user sets.

What you describe as a potential solution is exactly how I would do it. Destroying all the prior notifications and adding new ones is just writing data to the device, so it's not any more intensive than a local database write.

Here's how I've done it in one of my apps. This assumes you have an array of reminder objects with various properties used to show info about the notification. This is for iOS. The code for macOS is slightly different, but I can provide it if you need it.

import UIKit
import UserNotifications

func setupNotifications(){

  //Clear all the old notifications
  UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
  
  //Build new notifications
  for reminder in reminders{
    
    let notification = UNMutableNotificationContent()
    
    //Make sure we have a date property (reminder.date is a Date? optional)
    guard let date = reminder.date else{ continue }
    
    //Create a date components object from the reminder date
    let reminderDateComponents = Calendar.current.dateComponents([.year, .month, .day], from: date)
    
    //Set up a notification trigger in the future
    let trigger = UNCalendarNotificationTrigger(dateMatching: reminderDateComponents, repeats: false)
  
    notification.title = "Reminder Title"
    notification.body = "\(reminder.name) is due on \(date)."
    notification.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "Reminder.wav"))
    
    //Register the notification request
    let request = UNNotificationRequest(identifier: reminder.id, content: notification, trigger: trigger)
    
    UNUserNotificationCenter.current().add(request) { error in
      if let error = error{
        print("Error scheduling notification: \(error.localizedDescription)")
      }
    }

  }

}

You can then call setupNotifications() somewhere in your app wherever your data gets updated (like after a sync).

Related