I have a situation where tapping on a NavigationLink on an item from a SwiftData Query results in an infinite loop, causing the app the freeze. If you run the code, make sure to add at least 1 item, then tap on it to see the issue.
Here is the code for a small sample app I made to illustrate the issue:
import SwiftUI
import SwiftData
@main
struct TestApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([
Item.self
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
let container = try ModelContainer(for: schema, configurations: [modelConfiguration])
return container
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
struct ContentView: View {
var body: some View {
NavigationStack {
ListsView()
}
}
}
struct ListsView: View {
@Environment(\.modelContext) private var modelContext
@Query(filter: #Predicate<Item> { _ in true })
private var items: [Item]
var body: some View {
List(items) { item in
NavigationLink {
ItemDetail()
} label: {
VStack {
Text("\(item.name) | \(item.date.formatted())")
}
}
}
Button("Add") {
let newItem = Item(name: "Some item", date: .now)
modelContext.insert(newItem)
try? modelContext.save()
}
}
}
struct ItemDetail: View {
private var model = ItemModel()
var body: some View {
VStack {
Text("detail")
}
}
}
fileprivate var count = 0
class ItemModel {
var value: Int
init() {
value = 99
print("\(count)")
count += 1
}
}
@Model
final class Item {
let name: String
let date: Date
init(name: String, date: Date) {
self.name = name
self.date = date
}
}
In the test app above, the code in the initializer of ItemModel
will run indefinitely. There are a few things that will fix this issue:
- comment out the
private var model = ItemModel()
line inItemDetail
view - replace the @Query with a set list of
Item
s - move the contents of the
ListsView
into theContentView
instead of referencingListsView()
inside theNavigationStack
But I'm not sure why this infinite loop is happening with the initializer of ItemModel
. It seems like a SwiftData and/or SwiftUI bug, because I don't see a reason why this would happen. Any ideas? Has anyone run into something similar?