SwiftUI导航栏项目在向后滑动失败时出现混乱

16

我有一个 ListView, TasksViewEditView

流程如下:您有一个列表单元格,您点击单元格会进入TasksView。在TasksView中,如果单击行,则会进入EditView

当我向后滑动一半以导航到先前的视图时,导航栏会变得混乱并重叠。如果使用navigationBarItem-(button),则主要会出现此问题。

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时,相同的问题会发生。
以下是该错误的演示: enter image description here 有人知道如何修复这个错误吗?
编辑:
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来在删除当前视图时关闭它。然而,我仍然遇到了与上面动画展示的相同的故障。

更新:

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")
        }))
}

}
}

以上代码重现了该错误。当您单击“这是一个测试”按钮,然后稍微向后滑动,然后返回到上一个视图时,您将看到导航栏变得混乱不堪!


如何创建一个最小化、可复现的示例。 - Asperi
3个回答

15

我找到了一个简单的解决方案来修复你的问题,将这个添加到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")
            }))
    }
}
} 

这并没有解决问题。 - Lawrence Tan
我已经更新了我的答案,以显示我正在使用的代码。我已在真实设备和各种模拟器上进行了测试,没有任何问题。您能告诉我们这段代码在哪个设备/系统上无法工作吗?我使用的是Xcode 11.5和11.6 beta,在mac 10.15上目标为iOS 13.5和Mac Catalyst。 - workingdog support Ukraine
这将如何转换为iPad版本?使用StackNavigationViewStyle,您基本上会删除iPad的主细节视图布局。 - Osama Naeem
1
我已在iPad上进行了测试,无论是否添加我的内容,它都运行良好。你有一台设备无法运行该解决方案吗? - workingdog support Ukraine

3

我曾经也遇到过同样的问题,所以我决定使用一个视图修饰符来创建一个自定义的导航栏,并且现在我正在使用它。 但是我现在认为我找到了另一种解决方案。 尝试在NavigationLink后面添加.isDetailLink(false)

NavigationLink(destination: DestinationView()) {
    Text("This is a test")
}
.isDetailLink(false)


0

使用.toolbarToolbarItem代替旧的.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()
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接