问题描述
在练习NavigationLink和NavigationDestination跳转页面时,Xcode预览界面中点击NavigationLink,发现跳转到对应页面后,马上跳回原来的页面。

同时,在使用预览的过程中,Xcode没有报错。
运行模拟器,在点击NavigationLink后,发现Xcode存在如下报错:
A NavigationLink is presenting a value of type “Int” but there is no matching navigationDestination declaration visible from the location of the link. The link cannot be activated.
Note: Links search for destinations in any surrounding NavigationStack, then within the same column of a NavigationSplitView.
解决问题
经过排查发现原因为,ContentView 和 PersonDetailView 中分别创建了自己的 NavigationStack,导致导航堆栈被重置。
在 SwiftUI 中,导航堆栈应该是整个导航流程的“全局容器”。如果在一个视图内创建了新的 NavigationStack,那么导航上下文会被覆盖或重置,导致跳转后立即返回到上一个视图。

解决方案为:
只在根视图(ContentView)中使用一个 NavigationStack,而在子视图(PersonDetailView)中直接布局内容,而不是再创建新的 NavigationStack。

删除PersonDetailView的NavigationStack代码:
// PersonDetailView
var body: some View {
// NavigationStack { 删除子视图的NavigationStack
List(adults) { user in
HStack {
Text("姓名:\(user.name),")
Text("年龄:\(user.age)")
}
}
// }
}
问题得到解决:

完整代码
ContextView文件
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var context
@Query var adults: [Person]
@State private var selectAge: Int = 18
var body: some View {
NavigationStack {
VStack {
// 列表展示查询结果
List {
Section("人员名单") {
ForEach(adults, id: \.self) { person in
Text("\(person.name),年龄:\(person.age)")
}
}
}
.frame(height: 330) // 限制列表的高度
VStack {
Text("筛选结果页面(比如年龄大于 \(selectAge) 的人员)")
Picker("选择年龄", selection: $selectAge) {
ForEach(1...100, id: \.self) { age in
Text("\(age)").tag(age)
}
}
.pickerStyle(WheelPickerStyle())
NavigationLink(value:selectAge) {
Text("查询")
.frame(maxWidth: 300)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
Spacer()
}
.navigationTitle("列表")
.navigationDestination(for: Int.self) { age in
PersonDetailView(age: age)
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("添加测试数据") {
try? context.delete(model: Person.self)
context.insert(Person(name: "李四", age: 7))
context.insert(Person(name: "章三", age: 58))
context.insert(Person(name: "王五", age: 24))
context.insert(Person(name: "北方", age: 47))
context.insert(Person(name: "卫子夫", age: 15))
context.insert(Person(name: "鸥玉", age: 35))
}
}
}
}
}
}
#Preview {
ContentView()
.modelContainer(for: Person.self)
}
PersonDetailView文件
import SwiftUI
import SwiftData
struct PersonDetailView: View {
@Environment(\.modelContext) private var context
@Query var adults: [Person]
init(age: Int) {
_adults = Query(filter: #Predicate<Person> {
$0.age > age
})
}
var body: some View {
List(adults) { user in
HStack {
Text("姓名:\(user.name),")
Text("年龄:\(user.age)")
}
}
}
}
#Preview {
PersonDetailView(age:0)
.modelContainer(for: Person.self)
}