How to use CloudKit with MongoDB Realm in SwiftUI

CloudKit

CloudKit is a framework that provides an interface to connect user data with iCloud application containers.

With CloudKit, users can seamlessly update their application data on iCloud, such that they can seamlessly sync it across their Apple devices.

Pre-requisites

You will need to have an Apple Developer Membership to access CloudKit and other premium services provided by Apple Developer Team.

The membership fee for a personal account is 99 USD for one year. You can read more about it at the Apple Developers website.

Let’s get started

  • Fire up Xcode, and then create a SwiftUI project.

  • Open up the project, go to Signing & Capabilities, and add a capability. Search for iCloud, and add it.

  • Select Key-value storage and CloudKit services.

  • Create a container, and then add your container name followed by your bundle identifier. This is a good convention to follow.

You can also visit the CloudKit dashboard by clicking on the button CloudKit Dashboard to manage your databases. Here, we wouldn’t need that, since we will upload Realm Data for users only. i.e. We cannot view other users’ data and are strictly confined to them.

  • Now install IceCream, which is a CloudKit Realm package handler for SwiftUI.

Read about IceCream from their Github README.

You can follow the installation guide for Cocoapods, Swift Package Manager, and Carthage at the Github repository.

  • After IceCream is installed, head out to your Realm struct, and add a primary key if it doesn’t have one, followed by a bool parameter called isDeleted. By setting isDeleted to true, you can delete that particular field from iCloud, which is handled by IceCream.

For example:

class UserData: Object {
    @objc dynamic var id = NSUUID().uuidString
    @objc dynamic var isDeleted = false
    
    override class func primaryKey() -> String? {
        return "id"
    }

}
  • Also create two extensions CKRecordConvertible and CKRecordRecoverable and leave them blank.

For example:

extension UserData: CKRecordConvertible {
    
}

extension UserData: CKRecordRecoverable {
    
}

Remember to turn on Background Modes and check Background fetch and Remote notification.

  • Now you can simply start the sync engine in your init() function such that the engine will automatically update data in iCloud.
var syncEngine: SyncEngine?
syncEngine = SyncEngine(objects: [
    SyncObject(type: UserData.self)])
  • Now reload your app. Remember to delete the .realm file, since new data has been added to the Realm file. Also, if you run it on a simulator, you will not be able to view changes from iCloud. You will have to run it on a physical iPhone. You might come across the following warning while the app runs on a simulator.
[CK] Could not validate account info cache. (This is a potential performance issue.)

Do run the app on an iCloud-enabled physical iPhone, and then add some data. Delete the app with the data. On reinstalling you’ll find the old data from iCloud.

For any troubleshooting related to CloudKit, or Ice Cream, visit Apple Developer Forums or the issues section at IceCream Github Repository.

Free Resources