CoreData, CloudKit integration in SwiftUI a visual guide

Amit Srivastava
6 min readAug 2, 2023

--

SwiftUI, CloudKit

CloudKit framework allows users to access and sync data in their iCloud containers with the various devices that are using the same iCloud account. CloudKit also provides a generous quota to its users. In order to use CloudKit in your apps you will need a paid developer account.

I will try and explain integrating CloudKit using SwiftUI and. use images to show each and every step as the problems with CloudKit integration often arises due to missing just a step or two.

So start by creating new project and keep the Use Core Data and Host in CloudKit checked

Now open the Persistence file that is created as a result of adding these options

delete the preview closure

Your Persistence file should look like below

import CoreData

struct PersistenceController {
static let shared = PersistenceController()

let container: NSPersistentCloudKitContainer

init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "BooksDemo")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
}
}

here this line shows the name of the model created for you , its same as the name of your project, in my case i named it BooksDemo hence
container = NSPersistentCloudKitContainer(name: “BooksDemo”)

Now go to ContentView, we will add two fields here bookName and authorName and a button to save the data to coredata and then it will sync with CloudKit, so create a ContentView file as below

import SwiftUI
import CoreData

struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext

@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Books.authorName, ascending: true)], animation: .default) var booksData: FetchedResults<Books>

@State private var bookName = ""
@State private var authorName = ""

var body: some View {
VStack(alignment: .leading, spacing: 16) {
Section {
TextField("Enter Book Name", text: $bookName)
TextField("Enter Author Name", text: $authorName)
Button {
//-- action coming up

} label: {
Text("Save Data")
}

}
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environment(\.managedObjectContext, PersistenceController.shared.container.viewContext)
}
}

Now click on your model file , in my case BooksDemo, there is an Item entity in place already, click on it and press backspace to delete it, then go to bottom and press the “+” sign that says add entity

Then call this Books

press the “+” sign and attributes, i added authorName and bookName with String data type.

Now its time to add capabilities to our project so we can communicate with cloudkit.

Select signing and capability

Then click on Capability tab and add type cloud in search bar ,you will see cloud symbol iCloud written double click and add it to your project.

Then in services add CloudKit

Then click on the + sign

Add your bundle id here and press the refresh button.

Then click on capabilities again and add background modes and select remote notifications.

Then click on cloudkit console button, you will go to your cloudkit console

Click on cloud kit database

here at the top where you might see a warning like Error loading container, there will be a drop down list , select the bundle identifier from there, this is import and as this will be the container of your current project.

then come back to content view and add code to your save data button, the file will look like below

import SwiftUI
import CoreData

struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext

@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Books.authorName, ascending: true)], animation: .default) var booksData: FetchedResults<Books>

@State private var bookName = ""
@State private var authorName = ""

var body: some View {
VStack(alignment: .leading, spacing: 16) {
Section {
TextField("Enter Book Name", text: $bookName)
TextField("Enter Author Name", text: $authorName)
Button {
//-- save and sync with cloudkit
let books = Books(context: viewContext)
books.authorName = authorName
books.bookName = bookName
do {
try viewContext.save()
} catch {
print("data was not saved")
}
} label: {
Text("Save Data")
}

}
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environment(\.managedObjectContext, PersistenceController.shared.container.viewContext)
}
}

Now go back to your cloudkit console and click on schema , you will see a name CD_Books this is CoreData Books entity that we had created

Your data is now saved on cloudkit , but we can do better

Click on CD_Books record type , at top right corner click Edit indexes

Now at the bottom of screen there is an option called Add basic index, click on it

Click on it and at bottom select recordName from drop down list and Queryable and press save changes

Now go back to Data tap and select private data, from first drop down, from second drop down your container , it will be some thing like com.apple.coredata.cloukit.zone and record type as CD_Books

Now press Query records in same row, you will see the records that you have added

Click on it and you can see the details

With simple steps and visual representation, i hope you will find it much easier to integrate cloud kit to your projects.

Thank you , please like and follow me on medium so i can continue to post more stories with your support and help other, hire iOS app developer for your app requirements.

--

--