Skip to content

Instantly share code, notes, and snippets.

Last active February 19, 2021 20:59
Show Gist options
  • Save randomor/be39af31c346220cfaca4f5a9b00252f to your computer and use it in GitHub Desktop.
Save randomor/be39af31c346220cfaca4f5a9b00252f to your computer and use it in GitHub Desktop.
SwiftUI 2020 + CloudKit + Core Data ZenJournal prototype:
import SwiftUI
import CoreData
let appTransactionAuthorName = "app"
struct ZenJournalApp: App {
var body: some Scene {
WindowGroup {
.environment(\.managedObjectContext, persistentContainer.viewContext)
var persistentContainer: NSPersistentCloudKitContainer = {
let container = NSPersistentCloudKitContainer(name: "ZenModel")
// Enable history tracking and remote notifications
guard let description = container.persistentStoreDescriptions.first else {
fatalError("###\(#function): Failed to retrieve a persistent store description.")
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
let id = ""
let options = NSPersistentCloudKitContainerOptions(containerIdentifier: id)
description.cloudKitContainerOptions = options
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
// do {
// // Uncomment to do a dry run and print the CK records it'll make
//// try container.initializeCloudKitSchema(options: [.dryRun, .printSchema])
// // Uncomment to initialize your schema
// try container.initializeCloudKitSchema()
// } catch {
// print("Unable to initialize CloudKit schema: \(error.localizedDescription)")
// }
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
container.viewContext.transactionAuthor = appTransactionAuthorName
// Pin the viewContext to the current generation token and set it to keep itself up to date with local changes.
container.viewContext.automaticallyMergesChangesFromParent = true
do {
try container.viewContext.setQueryGenerationFrom(.current)
} catch {
fatalError("###\(#function): Failed to pin viewContext to the current generation:\(error)")
return container
import SwiftUI
struct NavigationWrapper: View {
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(fetchRequest: ZenLog.allLogsFetchRequest()) var allLogs: FetchedResults<ZenLog>
var body: some View {
TimelineView(logs: self.allLogs)
import Foundation
import CoreData
class ZenLog: NSManagedObject, Identifiable {
@NSManaged var text: String?
@NSManaged var createdAt: Date?
extension ZenLog {
// ❇️ The @FetchRequest property wrapper in the ContentView will call this function
static func allLogsFetchRequest() -> NSFetchRequest<ZenLog> {
let request: NSFetchRequest<ZenLog> = ZenLog.fetchRequest() as! NSFetchRequest<ZenLog>
// ❇️ The @FetchRequest property wrapper in the ContentView requires a sort descriptor
request.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: true)]
return request
Copy link

randomor commented Jul 13, 2020

Not exactly sure if this is the right way to do it but it worked for me. Remember to add your .xcdatamodelId file to pair with your core data config. Also add the right entitlement for your app including iCloud CloudKit and remote notifications.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment