我是一名相当缺乏经验的 SwiftUI 程序员,所以我几乎总是对一件事或另一件事感到困惑。这次是导航。 我希望我的开始屏幕显示一个包含一些静态内容的列表,其中每行导航到一个动态列表,而我又想导航到一个视图以显示或编辑该行的内容。 在我的应用程序中,当我点击一行来显示/编辑它时,应用程序返回到开始视图。我不知何故弄乱了导航堆栈,或者做了其他错误 - 但什么?
我在一个小型演示应用程序中重新创建了该行为:
import SwiftUI
import SwiftUI
class InnerDataItem : Hashable, Identifiable, ObservableObject {
var id = UUID()
var innerInfo = ""
init(innerInfo: String = "") {
self.innerInfo = innerInfo
}
static func == (lhs: InnerDataItem, rhs: InnerDataItem) -> Bool {
lhs.innerInfo == rhs.innerInfo
}
func hash(into hasher: inout Hasher) {
hasher.combine(innerInfo)
}
}
class DataModel : Identifiable, ObservableObject {
let id: UUID = UUID()
@Published var info = "My String array"
@Published var innerData: [InnerDataItem] = []
init(info: String = "My String array", innerData: [InnerDataItem]) {
self.info = info
self.innerData = innerData
}
}
let testData = DataModel(
info: "Data model object",
innerData: [
InnerDataItem(innerInfo: "(1) Inner info One"),
InnerDataItem(innerInfo: "(1) Inner info Two"),
InnerDataItem(innerInfo: "(1) Inner info Three"),
])
struct DataListView: View {
@ObservedObject var data: DataModel
@State var editMode: EditMode = .inactive
var body: some View {
NavigationStack {
DataList(data: data)
.environment(\.editMode, $editMode)
.navigationDestination(for: InnerDataItem.self) { data in
DataEditItem(dataItem: data)
}
}
}
}
struct DataList: View {
@ObservedObject var data: DataModel
var body: some View {
List {
ForEach(data.innerData) { item in
NavigationLink(value: item) {
DataLine(dataItem: item)
}
}
}
}
}
struct DataLine: View {
@ObservedObject var dataItem: InnerDataItem
var body: some View {
VStack(alignment: .leading) {
Text(dataItem.innerInfo).font(.largeTitle)
}
}
}
struct DataEditItem: View {
@ObservedObject var dataItem: InnerDataItem
var body: some View {
Form {
Section(header: Text("Visningsnamn")) {
TextField("", text: $dataItem.innerInfo, prompt: Text(""))
}
}
}
}
struct ContentView: View {
var body: some View {
NavigationStack {
List {
NavigationLink {
DataListView(data: testData)
} label: {
Text("Link to data")
}
}
}
}
}
@main
struct ListNavTestAppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
#Preview {
ContentView()
}
好的,我尝试根据注释修改代码。并从@ObservableObject转换为@Observable。 代码仍然不起作用,但现在错误不同了。现在我在控制台中收到一条消息:
A navigationDestination for “ListNavTestApp.InnerDataItem” was declared earlier on the stack.
Only the destination declared closest to the root view of the stack will be used.
我的代码现在是这样的:
import SwiftUI
@Observable
class InnerDataItem : Hashable, Identifiable {
var id = UUID()
var innerInfo = ""
init(innerInfo: String = "") {
self.innerInfo = innerInfo
}
static func == (lhs: InnerDataItem, rhs: InnerDataItem) -> Bool {
lhs.innerInfo == rhs.innerInfo
}
func hash(into hasher: inout Hasher) {
hasher.combine(innerInfo)
}
}
@Observable
class DataModel : Identifiable {
let id: UUID = UUID()
var info = "My String array"
var innerData: [InnerDataItem] = []
init(info: String = "My String array", innerData: [InnerDataItem]) {
self.info = info
self.innerData = innerData
}
}
let testData = DataModel(
info: "Data model object",
innerData: [
InnerDataItem(innerInfo: "(1) Inner info One"),
InnerDataItem(innerInfo: "(1) Inner info Two"),
InnerDataItem(innerInfo: "(1) Inner info Three"),
])
struct DataListView: View {
var data: DataModel
var body: some View {
DataList(data: data)
}
}
struct DataList: View {
var data: DataModel
var body: some View {
List {
ForEach(data.innerData) { item in
NavigationLink(value: item) {
DataLine(dataItem: item)
}
}
}
.navigationDestination(for: InnerDataItem.self) { i in
DataEditItem(dataItem: i)
}
}
}
struct DataLine: View {
var dataItem: InnerDataItem
var body: some View {
VStack(alignment: .leading) {
Text(dataItem.innerInfo).font(.largeTitle)
}
}
}
struct DataEditItem: View {
@Bindable var dataItem: InnerDataItem
var body: some View {
Form {
Section(header: Text("Visningsnamn")) {
TextField("", text: $dataItem.innerInfo, prompt: Text(""))
}
}
}
}
struct ContentView: View {
@State private var gotoDataList = false
var body: some View {
NavigationStack {
List {
Button("Link to data") {
gotoDataList.toggle()
}
}
.navigationDestination(isPresented: $gotoDataList) {
DataListView(data: testData)
}
}
}
}
@main
struct ListNavTestAppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
#Preview {
ContentView()
}