SwiftUI导航:如何将详细信息视图切换到其他项目?

时间:2020-09-11 13:32:50

标签: swift swiftui

我正在努力实现以下导航行为: 用户可以从列表中选择一个触发该项目详细视图的项目。在该详细视图上,导航栏中有一个“添加”按钮,可打开用于添加其他项目的模式表。

到目前为止,一切都按预期进行。

但是添加项目后,我希望明细视图显示新项目。我试图将列表选择设置为新项目的ID。这将触发详细信息视图消失,列表选择新项目并在很短的时间内显示详细信息,然后详细信息视图再次消失并显示列表。

我尝试添加桥接绑定,并让列表视图不将选择设置为nil,这首先解决了问题,但随后“后退”按钮不再起作用。

请注意:我希望在详细信息视图上使用“添加”按钮,而不是在列表视图上使用“添加”按钮。

这是要测试的完整代码:

import Combine
import SwiftUI

struct ContentView: View {
    @ObservedObject private var state = AppState.shared
    
    var body: some View {
        NavigationView {
            List(state.items) {item in
                NavigationLink(destination: DetailView(item: item), tag: item.id, selection: self.$state.selectedId) {
                    Text(item.title)
                }
            }
            .navigationBarTitle("Items")
        }
    }
}

struct DetailView: View {
    var item: Item
    @State private var showForm = false

    var body: some View {
        Text(item.title)
            .navigationBarItems(trailing: Button("Add") {
                self.showForm = true
            })
            .sheet(isPresented: $showForm, content: { FormView() })
    }
}

struct FormView: View {
    @Environment(\.presentationMode) private var presentationMode
    private var state = AppState.shared

    var body: some View {
        Button("Add") {
            let id = self.state.items.count + 1
            self.state.items.append(Item(id: id, title: "Item \(id)"))
            self.presentationMode.wrappedValue.dismiss()
            
            self.state.selectedId = id
        }
    }
}

class AppState: ObservableObject {
    static var shared = AppState()

    @Published var items: [Item] = [Item(id: 1, title: "Item 1")]
    @Published var selectedId: Int?

}

struct Item: Identifiable {
    var id: Int
    var title: String
}

1 个答案:

答案 0 :(得分:1)

在您的方案中,需要使导航链接的目标位置独立,因此在更改目标位置时希望重新激活/无效它。

这是可行的方法。经过Xcode 11.7 / iOS 13.7的测试

demo

仅更新的代码:

struct ContentView: View {
    @ObservedObject private var state = AppState.shared
    @State private var isActive = false

    var body: some View {
        NavigationView {
            List(state.items) {item in
                HStack {
                    Button(item.title) {
                        self.state.selectedId = item.id
                        self.isActive = true
                    }
                    Spacer()
                    Image(systemName: "chevron.right").opacity(0.5)
                }
            }
            .navigationBarTitle("Items")
            .background(NavigationLink(destination: DetailView(), isActive: $isActive) { EmptyView() })
        }
    }
}

struct DetailView: View {
    @ObservedObject private var state = AppState.shared
    @State private var showForm = false

    @State private var fix = UUID()    // << fix for known issue with bar button misaligned after sheet
    var body: some View {
        Text(state.selectedId != nil ? state.items[state.selectedId! - 1].title : "")
            .navigationBarItems(trailing: Button("Add") {
                self.showForm = true
            }.id(fix))
            .sheet(isPresented: $showForm, onDismiss: { self.fix = UUID() }, content: { FormView() })
    }
}