A lightweight, testable, thread-safe Core Data stack and CRUD service written in Swift, designed for modular integration as a Swift Package.
- Swift 6.1+
- iOS 17+, macOS 14+
✅ Thread-safe Core Data stack using NSPersistentContainer
✅ Shared backgroundContext
and viewContext
for concurrent operations
✅ Insert, fetch, delete operations for any model conforming to CoreDataRepresentable
✅ Support for in-memory and persistent stores
✅ Modular, test-friendly design via protocols
✅ Ready for use in apps and frameworks
Add the following dependency in Xcode:
https://github.com/IhorIlin/CoreDataService.git
Or add manually to Package.swift
:
.package(url: "https://github.com/IhorIlin/CoreDataService.git", from: "0.3.0")
struct User: CoreDataRepresentable {
let id: UUID
let name: String
init(from entity: UserEntity) {
self.id = entity.id ?? UUID()
self.name = entity.name ?? ""
}
func toEntity(in context: NSManagedObjectContext) -> UserEntity {
let entity = UserEntity(context: context)
entity.id = id
entity.name = name
return entity
}
}
let config = DefaultCoreDataConfiguration(modelName: "MyModel", inMemory: false, bundle: .main)
let stack = DefaultCoreDataStack(configuration: config)
let service = DefaultCoreDataService(stack: stack)
Note: for unit tests, use bundle: .module
instead of .main
.
let user = User(id: UUID(), name: "Ihor")
try service.insertModel(user)
try service.save()
let users = try service.fetchModels(User.self)
Note: The fetchModels(_:with:)
method requires an explicit model type to be specified.
let fetchRequest = NSFetchRequest<UserEntity>(entityName: String(describing: UserEntity.self))
fetchRequest.predicate = NSPredicate(format: "name == %@", "Ihor")
let users = try await service.fetchModels(User.self, with: fetchRequest)
if let userToDelete = try service.fetchModels(User.self).first {
try service.deleteModel(userToDelete)
try service.save()
}
MIT License