为什么当我的底层数据源更新时 SwiftUI 会自动向后导航,我该如何避免这种行为?
Why does SwiftUI automatically navigate backwards when my underlying data source is updated and how can I avoid this behavior?
我有一个相当普通的设置:
- 使用
ForEach
组件创建的项目列表
- 点击某个项目时,我的应用会导航到详细视图
- 在详细视图中,用户可以执行更改基础项目的更新
问题是更新底层项目(它是一个结构)会导致 SwiftUI 自动向后导航。我认为这是因为该结构是一个不可变值并在更新期间被销毁,但是,它确实符合 Identifiable
所以我希望 SwiftUI 理解该项目仍然存在并且只需要更新而不是销毁。
有没有办法在不离开详细视图的情况下更新基础列表?
这是一个可重现的最小示例。
import SwiftUI
struct ContentView: View {
var body: some View {
DemoList(viewModel: ViewModel())
}
}
struct DemoItem: Codable, Hashable, Identifiable {
var id: UInt
var description: String
}
final class ViewModel: ObservableObject, Identifiable {
@Published var list = [
DemoItem(id: 1, description: "One"),
DemoItem(id: 2, description: "two")
]
/// This update causes SwiftUI to automatically navigate away from the detail view
func update(item: DemoItem) {
list = list.map { [=10=].id == item.id ? item : [=10=] }
}
}
struct DemoList: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
NavigationView {
ForEach(viewModel.list, id: \.self) { item in
NavigationLink(destination: DemoDetail(viewModel: self.viewModel, item: item)) {
Text(item.description)
}
}
}
}
}
struct DemoDetail: View {
@ObservedObject var viewModel: ViewModel
var item: DemoItem
var body: some View {
Text(item.description)
.onTapGesture {
let newItem = DemoItem(id: self.item.id, description: UUID().uuidString)
self.viewModel.update(item: newItem)
}
}
}
只需从 ForEach 中删除 id,它就会停止向后导航
ForEach(viewModel.list) { item in
NavigationLink(destination: DemoDetail(viewModel: self.viewModel, item: item)) {
Text(item.description)
}
}
这应该可以解决您的问题:
NavigationView {
//Your views here
}.navigationViewStyle(.stack)
这是由于 iOS 15.0.1.
中的错误造成的
您可以从这里找到详细信息 forum thread
我有一个相当普通的设置:
- 使用
ForEach
组件创建的项目列表 - 点击某个项目时,我的应用会导航到详细视图
- 在详细视图中,用户可以执行更改基础项目的更新
问题是更新底层项目(它是一个结构)会导致 SwiftUI 自动向后导航。我认为这是因为该结构是一个不可变值并在更新期间被销毁,但是,它确实符合 Identifiable
所以我希望 SwiftUI 理解该项目仍然存在并且只需要更新而不是销毁。
有没有办法在不离开详细视图的情况下更新基础列表?
这是一个可重现的最小示例。
import SwiftUI
struct ContentView: View {
var body: some View {
DemoList(viewModel: ViewModel())
}
}
struct DemoItem: Codable, Hashable, Identifiable {
var id: UInt
var description: String
}
final class ViewModel: ObservableObject, Identifiable {
@Published var list = [
DemoItem(id: 1, description: "One"),
DemoItem(id: 2, description: "two")
]
/// This update causes SwiftUI to automatically navigate away from the detail view
func update(item: DemoItem) {
list = list.map { [=10=].id == item.id ? item : [=10=] }
}
}
struct DemoList: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
NavigationView {
ForEach(viewModel.list, id: \.self) { item in
NavigationLink(destination: DemoDetail(viewModel: self.viewModel, item: item)) {
Text(item.description)
}
}
}
}
}
struct DemoDetail: View {
@ObservedObject var viewModel: ViewModel
var item: DemoItem
var body: some View {
Text(item.description)
.onTapGesture {
let newItem = DemoItem(id: self.item.id, description: UUID().uuidString)
self.viewModel.update(item: newItem)
}
}
}
只需从 ForEach 中删除 id,它就会停止向后导航
ForEach(viewModel.list) { item in
NavigationLink(destination: DemoDetail(viewModel: self.viewModel, item: item)) {
Text(item.description)
}
}
这应该可以解决您的问题:
NavigationView {
//Your views here
}.navigationViewStyle(.stack)
这是由于 iOS 15.0.1.
中的错误造成的
您可以从这里找到详细信息 forum thread