【发布时间】:2022-10-14 03:26:21
【问题描述】:
我正在下面的示例代码中寻找以下错误的解决方案。我尝试使用 SwiftUI 4 和 iOS 16.0 导航 API 变更集来实现导航器模式。
下面的示例将在 Xcode 14.0+ 中编译,如果在模拟器或具有 iOS 16.0 的设备中运行将产生我所描述的错误。我想知道这是缺乏知识还是平台错误。通过我的日志,我可以看到,当我用不完整的向后滑动手势引发错误时,导航路径的元素计数上升到 2,而实际上它应该在根处返回 0,并且在第一层只保留 1 个元素看法。
有没有办法可以更好地管理这种视图层次结构的路径?或者,这是一个平台级别的错误?
import SwiftUI
enum AppViews: Hashable {
case kombuchaProductsView
case coffeeProductsView
case customerCartView
}
struct RootView: View {
@StateObject var drinkProductViewModel = DrinkProductViewModel()
var body: some View {
NavigationStack(path: self.$drinkProductViewModel.navPath) {
List {
Section("Products") {
NavigationLink(value: AppViews.kombuchaProductsView) {
HStack {
Text("View all Kombuchas")
Spacer()
Image(systemName: "list.bullet")
}
}
NavigationLink(value: AppViews.coffeeProductsView) {
HStack {
Text("View all Coffees")
Spacer()
Image(systemName: "list.bullet")
}
}
}
Section("Checkout") {
NavigationLink(value: AppViews.customerCartView) {
HStack {
Text("Cart")
Spacer()
Image(systemName: "cart")
}
}
}
}
.navigationDestination(for: AppViews.self) { appView in
switch appView {
case .kombuchaProductsView:
KombuchaProductsView(drinkProductViewModel: self.drinkProductViewModel)
case .coffeeProductsView:
CoffeeProductsView(drinkProductViewModel: self.drinkProductViewModel)
case .customerCartView:
Text("Not implemented")
}
}
}
.onAppear {
print("RootView appeared.")
print("Nav stack count: \(self.drinkProductViewModel.navPath.count) (RootView)")
}
}
}
struct KombuchaProductsView: View {
@State var drinkProductViewModel: DrinkProductViewModel
var body: some View {
ScrollView {
VStack(spacing: 16) {
ForEach(drinkProductViewModel.kombuchaProducts, id: \.self) { kombucha in
NavigationLink {
KombuchaView(
drinkProductViewModel: self.drinkProductViewModel,
kombucha: kombucha
)
} label: {
HStack {
Text(kombucha.name)
Spacer()
Text("$\(kombucha.price)")
Image(systemName: "chevron.right")
.foregroundColor(.gray)
}
}
Divider()
}
.padding()
}
}
.navigationTitle("Kombucha Selection")
.onAppear {
print("KombuchaProductsView appeared.")
print("Nav stack count: \(self.drinkProductViewModel.navPath.count) (KombuchaProductsView)")
}
.onDisappear {
print("KombuchaProductsView disappeared")
}
}
}
struct CoffeeProductsView: View {
@State var drinkProductViewModel: DrinkProductViewModel
var body: some View {
ScrollView {
VStack(spacing: 16) {
ForEach(drinkProductViewModel.coffeeProducts, id: \.self) { coffee in
NavigationLink {
CoffeeView(
drinkProductViewModel: self.drinkProductViewModel,
coffee: coffee
)
} label : {
HStack {
Text(coffee.name)
Spacer()
Text("$\(coffee.price)")
Image(systemName: "chevron.right")
.foregroundColor(.gray)
}
}
Divider()
}
.padding()
}
}
.navigationTitle("Coffee Selection")
.onAppear {
print("CoffeeProductsView appeared")
print("Nav stack count: \(self.drinkProductViewModel.navPath.count) (CoffeeProductsView)")
}
.onDisappear {
print("CoffeeProductsView disappeared")
}
}
}
struct KombuchaView: View {
@ObservedObject var drinkProductViewModel: DrinkProductViewModel
@State var kombucha: Kombucha
var body: some View {
VStack {
Text("Price:")
.font(.title)
Text("\(kombucha.price)")
.font(.callout)
}
.navigationTitle(kombucha.name)
.onAppear {
print("Nav stack count: \(self.drinkProductViewModel.navPath.count) (KombuchaView)")
}
}
}
struct CoffeeView: View {
@ObservedObject var drinkProductViewModel: DrinkProductViewModel
@State var coffee: Coffee
var body: some View {
VStack {
Text("Price:")
.font(.title)
Text("\(coffee.price)")
.font(.callout)
}
.navigationTitle(coffee.name)
.onAppear {
print("Nav stack count: \(self.drinkProductViewModel.navPath.count) (CoffeeView)")
}
}
}
对于那些对精确编译我的示例感兴趣的人,下面是我的模拟 ViewModel(它只是保存静态数据 - 它纯粹是为了这个探索而构建的):
class DrinkProductViewModel: ObservableObject {
@Published var navPath = NavigationPath()
@Published var customerCart = [Any]()
@Published var kombuchaProducts = [Kombucha]()
@Published var coffeeProducts = [Coffee]()
init() {
// Let's ignore networking, and assume a bunch of static data
self.kombuchaProducts = [
Kombucha(name: "Ginger Blast", price: 4.99),
Kombucha(name: "Cayenne Fusion", price: 6.99),
Kombucha(name: "Mango Tango", price: 4.49),
Kombucha(name: "Clear Mind", price: 5.39),
Kombucha(name: "Kiwi Melon", price: 6.99),
Kombucha(name: "Super Berry", price: 5.99)
]
self.coffeeProducts = [
Coffee(name: "Cold Brew", price: 2.99),
Coffee(name: "Nitro Brew", price: 4.99),
Coffee(name: "Americano", price: 6.99),
Coffee(name: "Flat White", price: 5.99),
Coffee(name: "Espresso", price: 3.99)
]
}
func addToCustomerCart() {
}
func removeFromCustomerCart() {
}
}
请注意:通过不完整的滑动手势,我的意思是用户开始从前缘拖动屏幕,然后按住它,然后将其返回到其起始位置并释放它,这样用户就不会离开,而是保持在当前视图中背部。然后返回父视图(不是根视图)将导致导航链接失效。
您可以通过未能从康普茶或咖啡详细视图(最深的子视图)完成向后滑动手势来观察我描述的错误,然后返回到产品列表视图之一并尝试单击导航之一链接(应该是死的)。
返回根视图通常会在运行时清除此场景并恢复 NavigationLink 功能。
【问题讨论】:
标签: swiftui drag swiftui-navigationlink ios16 swiftui-navigationstack