GithubHelp home page GithubHelp logo

sample-cloudkit-privatedb-sync's Introduction

CloudKit Samples: Private Sync with Subscriptions and Push

Goals

This project demonstrates using CloudKit Database Subscriptions and push notifications to keep two separate instances of an app in sync. Ideally it is run on both a simulator and a real device, and content changes made on the simulator are received and reflected on the device via CloudKit Subscriptions, similar to the functionality of the Notes or Photos apps.

Prerequisites

  • A Mac with Xcode 13 (or later) installed is required to build and test this project.
  • An iOS device which will receive CloudKit change notifications is required to install and run the app on.
  • An active Apple Developer Program membership is needed to create a CloudKit container and sign the app to run on a device.

Note: Simulators cannot register for remote push notifications. Running this sample on a device is required to receive CKSubscription push notifications and observe syncing functionality.

Setup Instructions

  1. Ensure you are logged into your developer account in Xcode with an active membership.
  2. In the “Signing & Capabilities” tab of the PrivateSync target, ensure your team is selected in the Signing section, and there is a valid container selected under the “iCloud” section.
  3. Ensure that both the simulator you wish to use and the device you will run the app on are logged into the same iCloud account.

Using Your Own iCloud Container

  • Create a new iCloud container through Xcode’s “Signing & Capabilities” tab of the PrivateSync app target.
  • Update the containerIdentifier property in Config.swift with your new iCloud container identifier.

How it Works

  • On first launch, the app creates a custom zone on the Private Database named “Contacts”, and subscribes to all record changes on that zone.
  • When running on a device, the app also registers with APNs (Apple Push Notification service), which is the mechanism for receiving information about changes through the aforementioned subscription.
  • After this initialization process, the app fetches the latest changes from the server, using a change token representing the last time changes were fetched and processed if available. On first launch, no local token is available, so all records are returned, and the token returned from this operation is saved.
  • The app’s main UI displays a list of Contacts. When the user adds a new Contact through the UI, a new record is created and saved to the database, and if successful, also saves this to a local store. This will trigger the UI to update and include the new Contact on the main list view.
  • Creating a new record triggers a notification to other devices which are registered for push notifications with the app through the CKRecordZoneSubscription created on first launch.
  • Devices receiving this notification will react by fetching the latest changes on the zone using the last known change token, and receive only the set of records that have changed since that change token was received. The records are updated locally and the UI now reflects the latest database state once again.

Example Flow

  1. Run the app on a device. Latest changes are fetched and a change token is stored.
  2. Repeat the above on a simulator, and add a new contact through the UI.
  3. The device receives a background push notification flagging that a change has occurred.
  4. The device fetches the changes, passing along the change token received in step 1. Only the new contact added in step 2 is returned and processed, and now shows on the UI.

Things To Learn

  • Creating a custom CloudKit Record Zone.
  • Creating a CloudKit Subscription that listens to database changes and sends a content-available push notification on change events.
  • Registering for push notifications with a SwiftUI-compatible UIApplicationDelegate class.
  • Receiving and handling a CKNotification.
  • Using a cached CKServerChangeToken to fetch only record changes and deletions since the last sync.
  • Adding, removing, and merging remote changes into a local cache, and reflecting those changes live in a UI.

Note on Swift Concurrency

This project uses Swift concurrency APIs. A prior completionHandler-based implementation has been tagged pre-async.

Further Reading

sample-cloudkit-privatedb-sync's People

Contributors

sjrmanning avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.