Skip to content

Instantly share code, notes, and snippets.

@azamsharpschool
Created May 26, 2026 20:22
Show Gist options
  • Select an option

  • Save azamsharpschool/d66674a274e9a80825e5189c263ef235 to your computer and use it in GitHub Desktop.

Select an option

Save azamsharpschool/d66674a274e9a80825e5189c263ef235 to your computer and use it in GitHub Desktop.
//
// ContentView.swift
// CustomDataStore
//
// Created by Mohammad Azam on 5/24/26.
//
import SwiftUI
import SwiftData
import Foundation
@Model
class Book {
var name: String
var author: String
init(name: String, author: String) {
self.name = name
self.author = author
}
}
@Model
class Review {
var subject: String
var desc: String
var book: Book?
init(subject: String, desc: String) {
self.subject = subject
self.desc = desc
}
}
final class JSONStoreConfiguration: DataStoreConfiguration {
typealias Store = JSONStore
var name: String
var schema: Schema?
var fileURL: URL
init(name: String, schema: Schema? = nil, fileURL: URL) {
self.name = name
self.schema = schema
self.fileURL = fileURL
}
static func == (
lhs: JSONStoreConfiguration,
rhs: JSONStoreConfiguration
) -> Bool {
lhs.name == rhs.name
}
func hash(into hasher: inout Hasher) {
hasher.combine(name)
}
}
final class JSONStore: DataStore {
typealias Configuration = JSONStoreConfiguration
typealias Snapshot = DefaultSnapshot
var configuration: JSONStoreConfiguration
var name: String
var schema: Schema
var identifier: String
init(
_ configuration: JSONStoreConfiguration,
migrationPlan: (any SchemaMigrationPlan.Type)?
) throws {
self.configuration = configuration
self.name = configuration.name
self.schema = configuration.schema!
self.identifier = configuration.fileURL.lastPathComponent
}
}
extension JSONStore {
private func getSnapshots() throws -> [PersistentIdentifier: DefaultSnapshot] {
let fileURL = configuration.fileURL
guard FileManager.default.fileExists(atPath: fileURL.path(percentEncoded: false)) else { return [: ] }
let data = try Data(contentsOf: fileURL)
// get already stored snapshots from the database
let snapshots = try JSONDecoder().decode([DefaultSnapshot].self, from: data)
var result: [PersistentIdentifier: DefaultSnapshot] = [: ]
for snapshot in snapshots {
result[snapshot.persistentIdentifier] = snapshot
}
return result
}
private func persistSnapshots(_ snapshots: [PersistentIdentifier: DefaultSnapshot]) throws {
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
encoder.outputFormatting = [
.prettyPrinted,
.sortedKeys
]
let data = try encoder.encode(Array(snapshots.values))
try data.write(to: configuration.fileURL, options: .atomic)
}
func save(_ request: DataStoreSaveChangesRequest<DefaultSnapshot>) throws -> DataStoreSaveChangesResult<DefaultSnapshot> {
print("save fired")
var storedSnapshots = try getSnapshots()
var remappedIdentifiers: [
PersistentIdentifier: PersistentIdentifier
] = [:]
for snapshot in request.inserted {
let permanentIdentifier = try PersistentIdentifier.identifier(for: identifier, entityName: snapshot.persistentIdentifier.entityName, primaryKey: UUID())
let permanentSnapshot = snapshot.copy(persistentIdentifier: permanentIdentifier, remappedIdentifiers: remappedIdentifiers)
storedSnapshots[permanentIdentifier] = permanentSnapshot
remappedIdentifiers[snapshot.persistentIdentifier] = permanentIdentifier
}
for snapshot in request.deleted {
storedSnapshots[snapshot.persistentIdentifier] = nil
}
for snapshot in request.updated {
storedSnapshots[snapshot.persistentIdentifier] = snapshot
}
// write snapshots
try persistSnapshots(storedSnapshots)
return DataStoreSaveChangesResult(for: identifier, remappedIdentifiers: remappedIdentifiers)
}
func fetch<T>(_ request: DataStoreFetchRequest<T>) throws -> DataStoreFetchResult<T, DefaultSnapshot> where T : PersistentModel {
print("fetch fired")
let snapshots = try getSnapshots()
let fetchedSnapshots = snapshots.values.filter {
$0.persistentIdentifier.entityName == "\(T.self)"
}
return DataStoreFetchResult(descriptor: request.descriptor, fetchedSnapshots: fetchedSnapshots)
}
}
struct ContentView: View {
@Query private var books: [Book]
@Environment(\.modelContext) private var context
var body: some View {
List {
Button("Save") {
let book = Book(name: "Book 2", author: "Azam")
context.insert(book)
let review = Review(subject: "Subject 1", desc: "Description")
// book.reviews.append(review)
}
ForEach(books) { book in
Text(book.name)
/*
Text("Review count: \(book.reviews.count)")
ForEach(book.reviews) { review in
VStack {
Text(review.subject)
Text(review.desc)
}
}*/
}
}
}
}
//
// CustomDataStoreApp.swift
// CustomDataStore
//
// Created by Mohammad Azam on 5/24/26.
//
import SwiftUI
import SwiftData
@main
struct CustomDataStoreApp: App {
let container: ModelContainer
init() {
do {
let fileURL = URL.documentsDirectory.appending(
path: "books.json",
directoryHint: .notDirectory
)
print(fileURL)
let configuration = JSONStoreConfiguration(
name: "JSONStore",
fileURL: fileURL
)
self.container = try ModelContainer(
for: Book.self,
configurations: configuration
)
} catch {
fatalError("Unable to create model container: \(error.localizedDescription)")
}
}
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(container)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment