After updating Xcode to 13.4 my core data persistence stack started to fail for SwiftUI previews and Xcode Unit tests.
Error message:
Unresolved error Error Domain=NSCocoaErrorDomain Code=134081 "(null)" UserInfo={NSUnderlyingException=Can't add the same store twice}, ["NSUnderlyingException": Can't add the same store twice ...
Persistence stack:
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentContainer
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "Persistence")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions.append(description)
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
}
}
Usage for SwiftUI previews:
struct MyScreen_Previews: PreviewProvider {
static var previews: some View {
MyScreen()
.environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}
Extension to support SwiftUI preview:
extension PersistenceController {
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
// Pre-fill core data with required information for preview.
}
}
CodePudding user response:
There's a mistake in your code, when you append to the array of descriptions you now have 2 descriptions.
Change it to:
let description = container.persistentStoreDescriptions.first!
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
// Load
CodePudding user response:
I noticed, that after loading persistence storage error generated. This error (Can't add the same store twice), can be ignored for SwiftUI previews and Unit Tests.
To ignore this type of error needs to check XCTestSessionIdentifier and XCODE_RUNNING_FOR_PREVIEWS in the process info.
if let error = error as NSError? {
if ProcessInfo.processInfo.environment["XCTestSessionIdentifier"] == nil &&
ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == nil {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}