Migrate the Database From CloudKit to Firebase | by Hohyeon Moon | Dec, 2022

From CloudKit + Core Data to Firebase + Firestore

cloudkit logo

If the service only supports Apple devices, then using CloudKit and CoreData may be one of the best options. However, if you also need to support the web and Android, then the story becomes different.

Cloudkit JS can be used to access iCloud DB while supporting both web and Android. However, implementation is comparatively difficult, and requires users to have an Apple account to use the service.

If the plan is to support both web and Android in the future, CloudKit may be a slightly unsatisfactory solution. Since the service I’m running also plans to support web and Android, I replaced the existing CloudKit with Firebase.

Firebase has many advantages over CloudKit, but we’ll focus on the most compelling of its advantages.

Firstly, users can log in and access the DB in a variety of ways. You can obviously use email and phone numbers as login method. Social logins are also supported, including Google Sign-in or Sign-in with Apple. More advanced features such as SAML login are also available.

Apart from this, Firebase has many useful and advanced features which are implemented immediately after use. However, if your service becomes larger, there may be a need for more flexible features and pricing plans. The good thing here is that if development resources are abundant, it can be extended to GCP (Google Cloud Platform).

Last but not least, Firestore is the DB service of Firebase and supports offline mode. Therefore, we don’t have to worry about the local database, which is convenient when developing for mobile devices.

The best scenario for migration is to extract the data from CloudKit’s iCloud database and move it to Firebase’s Firestore database. However, iCloud doesn’t support data extraction, so it can’t be migrated that way.

So, we should use a little trick here. When the data from CloudKit arrives in the user’s local DB, Core Data, you take that data and proceed with the migration to Firebase. To migrate, we are moving the data from CloudKit to Core Data and from Core Data to Firebase.

Our data was mainly split Facials And Tasks,

Therefore, Firestore will have Facials And Tasks Collections created to facilitate migration.

let database = Firestore.firestore().collection("Users").document("\(user.id)")

let facialsRef = database.collection("Facials")
let tasksRef = database.collection("Tasks")

each coredata, coreFacials And coreTasks will be passed by parameter migrateFacials And migrateTasksrespectively.

func migrateCloudKit(coreFacials: FetchedResults, coreTasks: FetchedResults) 
migrateFacials(coreFacials: coreFacials)
migrateTasks(coreTasks: coreTasks)

to displace Facialsa for-loop will iterate through all Facials data in CoreData when setting data with setData, To set the data, we need to match it to the Firestore data type.

func migrateFacials(coreFacials: FetchedResults) 
coreFacials.forEach coreFacial in
let facial = facialsRef.document(UUID().uuidString)

facial.setData([
"value": coreFacial.value // Example
])

migrateTasks Migrating can also be done in the same way. However, in this case, once setData is completed and the migration is over, a UserDefaults with the key migrated will be set to true, This ensures that the app does not go through a migration every time it is run.

func migrateTasks(coreTasks: FetchedResults) 
coreTasks.forEach coreTask in
if let uuid = coreTask.id?.uuidString
let task = tasksRef.document(uuid)

task.setData([
"due": coreTask.due ?? Date(), // Example
"text": coreTask.text ?? "" // Example
]) _ in
// Set migrated to true
UserDefaults.standard.set(true, forKey: "migrated")



Based on SwiftUI lifecycle, run migrateCloudKit In onAppear depends on the use of migration status UserDefaults,

.onAppear 
if !UserDefaults.standard.bool(forKey: "migrated")
migrateCloudKit(coreFacials: facials, coreTasks: tasks)

When this migration process is complete, all existing data will be moved to Firestore in Firebase. Now, modify the existing CoreData code to match Firebase, and the migration to Firebase is complete.

Feedback is welcome! Please let me know if anything is wrong :).

Leave a Reply