Configuring your AppDelegate

As mentioned, silent push notifications work very similar to the way background fetch works. Just like background fetch, there is a special AppDelegate method that is called when a silent push notification arrives. You need to implement this method so you can handle the incoming notifications and fetch the change data from CloudKit. Add the following method to AppDelegate:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

  guard let dict = userInfo as? [String: NSObject] else {
    completionHandler(.failed)
    return
  }

  cloudStore.handleNotification(dict) { result in
    completionHandler(result)
  }
}

This method is called by iOS when your app receives a silent push notification from CloudKit. This message doesn't do much apart from telling CloudStore to process the notification and then it calls completionHandler to inform iOS about the result of the fetch. As you can see, this is very similar to background fetch apart from the fact that this method is called when the CloudKit server sends a push message to the app instead of when iOS decides to do so.

Lastly, add the following code at the end of application(_:didFinishLaunchingWithOptions:):

cloudStore.subscribeToChangesIfNeeded { [weak self] error in
  DispatchQueue.main.async {
    application.registerForRemoteNotifications()
  }

  if error == nil {
    self?.cloudStore.fetchDatabaseChanges { fetchError in
      if let error = fetchError {
        print(error)
      }
    }
  }
}

The preceding code takes care of telling CloudStore to subscribe to changes. It also registers the app for remote notifications so CloudKit can send silent push messages to the app. Note that this type of push messaging does not require you to explicitly ask the user to send them push notifications. This type of permission is only required if you want to send the user visual push notifications. You can read more about push notifications in Chapter 22, Implementing Rich Notifications.

At this point, you can add a couple of records to your CloudKit database. Since you haven't implemented sending data to CloudKit yet, this is the best way for you to verify that your code works as expected. You should see the names of the movies and family members you have added in the CloudKit dashboard printed to the console. Once you have the app running, try adding a new family member while the app is open. You should see the name of the new family member appear in the console right after you add the record to the CloudKit dashboard. Pretty neat, right?

To use the private database in CloudKit, a user that is logged in to CloudKit on their device is required. Make sure to run your app on a physical device that has a logged-in iCloud user (preferably the same account you use as your Apple developer account) or log an iCloud user in on the simulator by navigating to the Settings app on the simulator.