SwiftUI - 表单中的 NavigationLink 单元格在详细信息弹出后保持突出显示

Bra*_*key 33 uikit ios swift swiftui

在 iOS 14 中,似乎NavigationLinks 在Form上下文中返回后不会被取消选择。对于Form Pickers 和任何其他导致View列表中另一个的呈现(为呈现单元格提供高亮上下文)也是如此。

我在 iOS 13 中没有注意到这种行为。

一旦其他视图被关闭,有没有办法“取消选择”突出显示的行?

示例代码:

struct ContentView: View {

    var body: some View {
        Form {
            NavigationLink(destination: Text("Detail")) {
                Text("Link")
            } 
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

(不同)示例视觉:

例子

Kuh*_*ann 21

在我的情况下,当在 myNavigationViewList/Form.

var body: some View {
    
    NavigationView {
        VStack {
            Text("This text DOES make problems.")
            List {
                NavigationLink(destination: Text("Doesn't work correct")) {
                    Text("Doesn't work correct")
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

将 Text()放在List之下不会产生任何问题:

var body: some View {
    
    NavigationView {
        VStack {
            List {
                NavigationLink(destination: Text("Does work correct")) {
                    Text("Does work correct")
                }
            }
            Text("This text doesn't make problems.")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这绝对是一个 XCode 12 错误。随着越来越多的人报告这个问题,它会越早得到解决。

  • 请参阅我更新的答案和一个简单的示例。Text() 只是产生问题的一个示例。Image() 和许多其他函数具有相同的行为。 (2认同)

Dav*_*ate 15

我也遇到了这个问题,并相信我找到了我的案例的根本原因。

在我的情况下,我有一个如下结构:

struct Page1View: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink("Page 2", destination: Page2View())
            }
                .listStyle(GroupedListStyle())
                .navigationBarTitle("Page 1")
        }
    }
}

struct Page2View: View {
    var body: some View {
        List {
            NavigationLink("Page 3", destination: Text("Page 3"))
        }
            .listStyle(GroupedListStyle())
            .navigationBarTitle("Page 2")
    }
}
Run Code Online (Sandbox Code Playgroud)

此问题会发生在 NavigationLink 到页面 3 上。在控制台输出中,使用该链接时会显示此错误:

2021-02-13 16:41:00.599844+0000 App[59157:254215] [Assert] displayModeButtonItem is internally managed and not exposed for DoubleColumn style. Returning an empty, disconnected UIBarButtonItem to fulfill the non-null contract.
Run Code Online (Sandbox Code Playgroud)

我发现我需要申请.navigationViewStyle(StackNavigationViewStyle())NavigationView,这解决了问题。

IE

struct Page1View: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink("Page 2", destination: Page2View())
            }
                .listStyle(GroupedListStyle())
                .navigationBarTitle("Page 1")
        }
            .navigationViewStyle(StackNavigationViewStyle())
    }
}

Run Code Online (Sandbox Code Playgroud)


小智 8

今天一直在与这个问题作斗争半天,来到这篇文章,帮助我理解这个问题是否出现TextButton或者NavigationView在我的情况下和其他东西之间List。我找到了对我有用的解决方案。只需.zIndex()为项目添加。.zIndex()必须高于 for ListTried with Xcode 12.5

var body: some View {
    NavigationView {
        VStack {
            Text("This text DOES make problems.")
                .zIndex(1.0)
            List {
                NavigationLink(destination: Text("Doesn't work correct")) {
                    Text("Doesn't work correct")
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说适用于 iOS 14.5 模拟器的 Xcode 12.5。 (2认同)

Bra*_*key 6

我做了更多的修补,结果证明这是由于UIHostingController嵌套在 a 中UINavigationController并使用该导航控制器造成的。更改导航堆栈以使用 SwiftUINavigationView解决了此问题。

与@pawello2222 在问题评论中所说的类似,我认为根本原因与 SwiftUI 在使用外部时不理解正确的导航层次结构有关UINavigationController

这只是修复了此问题的一个实例,根据我的视图结构,我仍在各种其他上下文中遇到此问题。

我已经向Apple提交了一份问题报告FB8705430,所以希望这个问题很快得到解决。

之前(损坏):

struct ContentView: View {
    var body: some View {
        Form {
             NavigationLink(destination: Text("test")) {
                 Text("test")
             }
        }
    }
}

// (UIKit presentation context)
let view = ContentView() 
let host = UIHostingController(rootView: view)
let nav = UINavigationController(rootViewController: host)
present(nav, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)

之后(工作):

struct ContentView: View {
    var body: some View {
        NavigationView {
            Form {
                NavigationLink(destination: Text("test")) {
                    Text("test")
                }
            }
        }
    }
}

// (UIKit presentation context)
let view = ContentView()
let host = UIHostingController(rootView: view)
present(host, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)

  • 我有同样的问题,但不幸的是这不起作用,因为我的初始视图控制器是 UIKit 表视图,并且是 UINavigationController 的根视图控制器。选择一行时,我推送一个视图控制器,在其中创建一个包装我的 SwiftUI 表单的 UIHostingController 实例,并将其添加为子视图控制器。如果我为表单提供自己的 NavigationView,我最终会得到来自 2 个导航控制器的 2 个导航栏。我尝试子类化 UIHostingController 而不是实例化它,但它不起作用。我希望对此有一个明确的解决方案。 (2认同)

Ami*_*ndi 6

这绝对是 中的一个错误List,目前,我的解决方法是List通过更改 id来刷新,如下所示:

struct YourView: View {
    @State private var selectedItem: String?
    @State private var listViewId = UUID()

    var body: some View {
            List(items, id: \.id) {
                NavigationLink(destination: Text($0.id), 
                               tag: $0.id, 
                               selection: $selectedItem) {
                  Text("Row \($0.id)")
                }
            }
            .id(listViewId)
            .onAppear {
                if selectedItem != nil {
                    selectedItem = nil
                    listViewId = UUID()
                }
            }
    } 
}
Run Code Online (Sandbox Code Playgroud)

我基于此制作了一个修饰符,您可以使用:

struct RefreshOnAppearModifier<Tag: Hashable>: ViewModifier {
    @State private var viewId = UUID()
    @Binding var selection: Tag?
    
    func body(content: Content) -> some View {
        content
            .id(viewId)
            .onAppear {
                if selection != nil {
                    viewId = UUID()
                    selection = nil
                }
            }
    }
}

extension View {
    func refreshOnAppear<Tag: Hashable>(selection: Binding<Tag?>? = nil) -> some View {
        modifier(RefreshOnAppearModifier(selection: selection ?? .constant(nil)))
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

List { ... }
  .refreshOnAppear(selection: $selectedItem)
Run Code Online (Sandbox Code Playgroud)