I'm having trouble resolving the error.
If I save data in view A and open view B, I get an error. If I open only view A, or only view B, there is no problem, but when I open a second view (A to B, B to A, etc.) I get an error.
Attached is the code that reproduces the problem. We would appreciate your cooperation.
No simulator is used. Xcode: Version 15.4 (15F31d) iPone11: 17.5.1
Thank you.
Error
error: Error: Persistent History (2) has to be truncated due to the following entities being removed: (
A
)
warning: Warning: Dropping Indexes for Persistent History
warning: Warning: Dropping Transactions prior to 2 for Persistent History
warning: Warning: Dropping Changes prior to TransactionID 2 for Persistent History
Code
import SwiftUI
import SwiftData
@main
struct issueApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(for: [A.self, B.self])
}
}
}
import SwiftUI
import SwiftData
struct ContentView: View {
@State var showAView: Bool = false
@State var showBView: Bool = false
var body: some View {
VStack {
Button("show A"){
showAView.toggle()
}
.sheet(isPresented: $showAView){
AView()
}
Button("show B"){
showBView.toggle()
}
.sheet(isPresented: $showBView){
BView()
}
}
}
}
struct AView: View {
@Environment(\.modelContext) var context
@Query private var list: [A]
let query = QueryData<A>()
var body: some View {
VStack {
if list.count > 0 {
VStack {
List {
ForEach(list, id: \.number){ item in
VStack {
Text(item.number)
}
}
}
Button("clear"){
try? context.delete(model: A.self)
}
}
} else {
Button("set"){
query.set(data: A(number: "1"))
}
}
}
}
}
struct BView: View {
@Environment(\.modelContext) var context
@Query private var list: [B]
let query = QueryData<B>()
var body: some View {
VStack {
if list.count > 0 {
VStack {
List {
ForEach(list, id: \.number){ item in
VStack {
Text(item.number)
}
}
}
Button("clear"){
try? context.delete(model: B.self)
}
}
} else {
Button("set"){
query.set(data: B(number: "1"))
}
}
}
}
}
class QueryData<T: PersistentModel> {
private var container: ModelContainer?
init() {
self.container = try? ModelContainer(for: T.self)
}
func set(data: T) {
guard let container = self.container else { return }
let context = ModelContext(container)
do {
try context.delete(model: T.self)
context.insert(data)
try context.save()
} catch {
print("error: \(error)")
}
}
}
@Model
final class A {
var number: String
init(number: String) {
self.number = number
}
}
@Model
final class B {
var number: String
init(number: String) {
self.number = number
}
}
When you set data in view A and open view B, your code does the following:
- Create a model container with model A.
- Insert an object of model A to the SwiftData store, which generates the history in the store.
- Create a model container with model B.
At step 3, the model schema only contains model B, which means the container knows nothing about model A, and so SwiftData cleans everything related to model A, including the history.
If you don't do step 2, no history is generated, and hence no need to truncate the history at step 3.
The error tells you that the history was truncated. Unless you need to find the history related to model A at step 3, which isn't quite right because the container's schema only contains B, the error won't matter, and you can safely ignore it.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.