向后滑动失败时,SwiftUI 导航栏项目变得混乱
Posted
技术标签:
【中文标题】向后滑动失败时,SwiftUI 导航栏项目变得混乱【英文标题】:SwiftUI navigation bar items going haywire when swipe back fails 【发布时间】:2020-09-16 21:30:39 【问题描述】:我有一个ListView
、TasksView
,然后是EditView
。
流程是这样的:你有一个列表单元格,你点击它会将你带到TasksView
当在TasksView
中点击一行时,它会将你带到EditView
。
当我向后滑动一半以导航到上一个视图时,导航栏会变得笨拙并重叠。它主要发生在我使用navigationBarItem - (按钮)时。
在TasksView (detailView)
中有一个列表和一些导航栏修饰符:
ZStack
List
// code here
.onAppear UITableView.appearance().separatorStyle = .none
.onDisappear UITableView.appearance().separatorStyle = .none
.background(Color("primaryBackground"))
.edgesIgnoringSafeArea(.bottom)
.navigationBarTitle("\(listItem.name ?? "")", displayMode: .inline)
.navigationBarItems(trailing:
Button(action: self.deleteList())
Image(systemName: "trash.circle.fill")
)
EditView
也是如此,当您在EditView
上滑动一半以返回TasksView
时,也会发生同样的事情。
以下是实际中的错误:
有人知道如何解决这个错误吗?
编辑:
struct TasksView: View
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var taskControl: TaskControl
@EnvironmentObject var addNewTaskData: AddNewTaskViewDataFlow
@ObservedObject var dataPickerData : DatePickerDataFlowV2
@FetchRequest(entity: ONList.entity(), sortDescriptors: []) var listsDataSource: FetchedResults<ONList>
@Environment(\.managedObjectContext) var listMOC
var listItem: ONList
var keyboardPublisher: AnyCancellable
// defining the presentationMode here
.......
ZStack
NavigationLink(destination: ListOptions(listItem: listItem), tag: 1, selection: self.$navigationSelectionTag)
EmptyView()
Color("primaryBackground")
.edgesIgnoringSafeArea(.top)
//... more code here
.onAppear
UITableView.appearance().separatorStyle = .none
self.taskControl.taskViewerSeperator = true
.onDisappear
UITableView.appearance().separatorStyle = .none
print("Bye Task View")
if UIDevice.current.userInterfaceIdiom == .phone
self.taskControl.taskViewerSeperator = false
self.keyboardPublisher.cancel()
.navigationBarTitle("\(listItem.name ?? "")", displayMode: .inline)
.background(Color("primaryBackground"))
.edgesIgnoringSafeArea(.bottom)
.navigationBarItems(trailing:
HStack
Button(action:
self.navigationSelectionTag = 1
, label:
Image(systemName: "gear")
)
Button(action:
self.deleteList()
)
Image(systemName: "trash.circle.fill")
.padding()
)
我什至没有在deleteList()
函数中使用presentationMode,以便在删除当前视图时将其关闭。但是,我仍然遇到与上面 gif 中所示相同的故障。
更新:
struct TestingCoreData: View
var body: some View
NavigationView
VStack
NavigationLink(destination: DestinationView())
Text("This is a test")
.navigationBarTitle(Text("Master"), displayMode: .inline)
.navigationBarItems(trailing:
Button(action:
print("tapped")
)
Text("Button")
)
struct DestinationView: View
@Environment(\.presentationMode) var presentationMode
var body: some View
List
Text("DestinationView")
.padding(.top, 100)
.navigationBarTitle(Text("Destination"), displayMode: .inline)
.navigationBarItems(trailing: Button(action:
self.presentationMode.wrappedValue.dismiss()
, label:
Text("second")
))
上面的代码重现了这个错误。当你点击“这是一个测试”按钮,然后你往回滑动一点,然后回到上一个视图,你会看到导航栏变得乱七八糟!
【问题讨论】:
How to create a Minimal, Reproducible Example 【参考方案1】:我找到了一个简单的解决方案来解决您的问题,将其添加到 NavigationView
NavigationView
....
.navigationViewStyle(StackNavigationViewStyle())
编辑:这是我用来在真实设备和各种模拟器上测试我的答案的代码。这解决了问题,如果您发现无法使用此功能的设备,请告诉我。
import SwiftUI
struct ContentView: View
var body: some View
NavigationView
VStack
NavigationLink(destination: DestinationView())
Text("This is a test")
.navigationBarTitle(Text("Master"), displayMode: .inline)
.navigationBarItems(trailing:
Button(action:
print("tapped")
)
Text("Button")
)
.navigationViewStyle(StackNavigationViewStyle())
struct DestinationView: View
@Environment(\.presentationMode) var presentationMode
var body: some View
List
Text("DestinationView")
.padding(.top, 100)
.navigationBarTitle(Text("Destination"), displayMode: .inline)
.navigationBarItems(trailing: Button(action:
self.presentationMode.wrappedValue.dismiss()
, label:
Text("second")
))
【讨论】:
这并不能解决问题。 我已更新我的答案以准确显示我正在使用的代码。我已经在真实设备和各种模拟器上对此进行了测试,没有任何问题。您能否告诉我们此代码在哪些设备/系统上不适合您。我在 mac 10.15 上使用了 Xcode 11.5 和 11.6 beta,目标是 ios 13.5 和 mac 催化剂。 这将如何转化为 iPad 版本?使用 StackNavigationViewStyle,您实际上是在移除 iPad 的主细节视图布局。 我在 iPad 上测试过,不管有没有我的添加,它都能很好地工作。您有解决方案不起作用的设备吗?【参考方案2】:我曾在同样的问题上苦苦挣扎。所以我决定制作一个带有视图修饰符的自定义导航栏,我正在使用它。
但我想我现在找到了另一种解决方案。
尝试在NavigationLink
之后添加.isDetailLink(false)
。
NavigationLink(destination: DestinationView())
Text("This is a test")
.isDetailLink(false)
【讨论】:
【参考方案3】:使用 .toolbar 和 ToolbarItem 而不是旧的 .navigationBarItems 可以解决问题。
还请注意,我已将导航修饰符从 Text 移至 List。
这是一个基于您的 UPDATE 代码的有效且经过测试的示例:
import SwiftUI
struct ContentView: View
var body: some View
NavigationView
VStack
NavigationLink(destination: DestinationView())
Text("This is a test")
.navigationBarTitle(Text("Master"), displayMode: .inline)
// use .toolbar instead of .navigationBarItems
.toolbar
ToolbarItem(placement: .navigationBarTrailing)
Button("Button", action:
print("tapped")
)
struct DestinationView: View
@Environment(\.presentationMode) var presentationMode
var body: some View
List
Text("DestinationView")
.padding(.top, 100)
.navigationBarTitle(Text("Destination"), displayMode: .inline)
// use .toolbar instead of .navigationBarItems
.toolbar
ToolbarItem(placement: .navigationBarTrailing)
Button("second", action:
self.presentationMode.wrappedValue.dismiss()
)
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【讨论】:
以上是关于向后滑动失败时,SwiftUI 导航栏项目变得混乱的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - navigationBarBackButtonHidden - 向后滑动手势?