I got a response to my feedback saying first "This crash arises from a document that has been closed with unsaved changes. In order to avoid this crash, ensure that the ModelContext is saved before closing the document." then "Thank you for filing the feedback report. We have deployed the fix. Please verify this issue with iOS 18.1 Beta 6".
Unfortunately it looks like the crashing part was fixed, but not the saving of the document. I think they are both equally important, since a document-based app is worthless if you cannot save your work.
This issue can still be seen using the unmodified FlashCards sample app.
Can we get some guidance on this as to whether or not it is now our responsibility to manually save changes? Prior to iOS18 this was not required, and likewise the sample project does not have any code to manually save.
This was tested with Beta 6 and Beta 7, using Xcode Version 16.1 beta 3 (16B5029d)
Post
Replies
Boosts
Views
Activity
This isn't the first time that document-based apps backed by SwiftData have been completely broken in an update.
Has anyone shipped a document-based app using SwiftData? I am wondering what the viability of this technology is, since my team is close to releasing a brand new app that relies on it. At this point I am terrified that it will keep breaking.
These aren't edge cases either. I am testing with Apple's (FlashCard) sample project to eliminate the possibility that my code is involved.
It seems to me that if anyone had tested the integrity of documents created by SwiftData (by closing and re-opening them), both this and the prior issue would have been found right away.
I am also able to easily reproduce this issue on an iPad running an unmodified version of the sample project, using the current release version of Xcode and iPadOS. It did not happen with the first document I created, but re-opening that document reveals that nothing saved. The second document did save changes, but it resulted in this error on close.
If this was a custom transformer, I would say you need to add ValueTransformer.setValueTransformer(NSSecureUnarchiveFromDataTransformer(), forName: NSValueTransformerName("NSSecureUnarchiveFromDataTransformer")) in your app's init(), but AFAIK UUID is Codable so I'm not sure you need a transformer here. Have you tried just ditching @Attribute(.transformable(by: "NSSecureUnarchiveFromDataTransformer"))?
FYI - I have been instructed by DTS to file a bug report for this issue. If anyone else is experiencing crashes or freezes when trying to implement a document-based app using SwiftData, please file a bug report so we can get the issue prioritized! If DTS are able to provide a work-around, I will post it here.
Response from DTS:
We believe this issue is a bug. Please file a bug report via Feedback Assistant (https://feedbackassistant.apple.com). For more information on Feedback Assistant, visit https://developer.apple.com/bug-reporting.
@Volker Runkel - This isn't something I would recommend going to production with, and I doubt it's a complete solution (I am still seeing SQLite errors in the debug console), but in order to continue development I have come up with the following work-around (at least until I hear back from DTS):
@main
struct TestDocumentAppApp: App {
var body: some Scene {
DocumentGroup(editing: .itemDocument, migrationPlan: TestDocumentAppMigrationPlan.self) {
IntermediarySceneView {
ContentView()
}
}
}
}
struct IntermediarySceneView<Content: View>: View {
@Environment(\.modelContext) private var originalModelContext
let content: Content
var body: some View {
content.environment(\.modelContext, originalModelContext.container.mainContext)
}
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
}
Basically, all this is doing is overriding the modelContext variable by traversing back to the container and grabbing the mainContext (AFAIK that is what it should be). It seems to prevent crashes in my limited testing, but there is a good chance there are issues elsewhere (I'm not sure where else the incorrect context may still be in use), so YMMV.
In case anyone wants to dig further into this issue, I was able to demonstrate that the underlying NSManagedObjectContext is being created with "main queue concurrency" for new documents, but "private queue concurrency" when re-opening a document (I am guessing this is the issue).
I added the following debug code to my main view (which has @Environment(\.modelContext) private var modelContext declared):
.onAppear(perform: {
if let moc = Mirror(reflecting: _modelContext.wrappedValue).descendant("_nsContext") as? NSManagedObjectContext {
switch moc.concurrencyType {
case .confinementConcurrencyType:
print("Confinement Concurrency")
case .privateQueueConcurrencyType:
print("Private Queue Concurrency")
case .mainQueueConcurrencyType:
print("Main Queue Concurrency")
}
moc.perform {
print("Context is on main thread??? -> \(Thread.current.isMainThread)")
}
}
})
Has anyone gotten SwiftData to work with SwiftUI's DocumentGroup? Even the (unmodified) Xcode Multiplatform document app template using SwiftData crashes when working with a saved document. I suspect that the DocumentGroup extension for SwiftData is not creating the context on the main thread, but only when re-opening saved documents. On macOS it crashes with the above mentioned error, but I have also seen this manifest as threading deadlocks (on the iPad and macOS).
With the all the work that was apparently put into SwiftData I'm incredulous that this would just flat out not work. I am hoping I am missing something, but (based on the unpopularity of UIManagedDocument) I fear that most people are simply not working with SwiftData in document-based apps or not using it with DocumentGroup (e.g. using it alongside Core Data).
I am hoping there is a work-around, as I have already invested a lot of time converting from Core Data.