ios - 如果未显示所有 NavigationLink,则 NavigationView 中 SwiftUI 的 NavigationLink `tag` 和 `selection` 将停止工作
问题描述
我在 aForm
中有一个项目列表NavigationView
,每个项目都有一个可以通过NavigationLink
. 当我向列表中添加一个新元素时,我想显示它的详细视图。为此,我使用接收为的 a @State var currentSelection
,并且每个元素都具有以下功能:NavigationLink
selection
tag
NavigationLink(
destination: DetailView(entry: entry),
tag: entry,
selection: $currentSelection,
label: { Text("The number \(entry)") })
令人惊讶的是,当列表中的元素多于屏幕(加上〜2)时,它会停止工作。问:为什么?我该如何解决它?
我做了一个最小的例子来复制行为:
import SwiftUI
struct ContentView: View {
@State var entries = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
@State var currentSelection: Int? = nil
var body: some View {
NavigationView {
Form {
ForEach(entries.sorted(), id: \.self) { entry in
NavigationLink(
destination: DetailView(entry: entry),
tag: entry,
selection: $currentSelection,
label: { Text("The number \(entry)") })
}
}
.toolbar {
ToolbarItem(placement: ToolbarItemPlacement.navigationBarLeading) { Button("Add low") {
let newEntry = (entries.min() ?? 1) - 1
entries.insert(newEntry, at: 1)
currentSelection = newEntry
} }
ToolbarItem(placement: ToolbarItemPlacement.navigationBarTrailing) { Button("Add high") {
let newEntry = (entries.max() ?? 50) + 1
entries.append(newEntry)
currentSelection = newEntry
} }
ToolbarItem(placement: ToolbarItemPlacement.bottomBar) {
Text("The current selection is \(String(describing: currentSelection))")
}
}
}
}
}
struct DetailView: View {
let entry: Int
var body: some View {
Text("It's a \(entry)!")
}
}
(我通过将列表减少到5个项目并在标签上设置填充来排除元素数量是核心问题label: { Text("The number \(entry).padding(30)") })
:)
正如您在屏幕记录中看到的那样,在达到关键元素数量后(通过预先或附加到列表),底部工作表仍然显示currentSelection
正在更新,但没有发生导航。
我使用了 iOS 14.7.1、Xcode 12.5.1 和 Swift 5。
解决方案
发生这种情况是因为没有渲染较低的项目,所以在层次结构中没有NavigationLink
这样的标签
我建议您使用ZStack
+ EmptyView
NavigationLink
“hack”。
我也在这里使用 LazyView ,多亏了@autoclosure
它让我通过 upwrapped currentSelection
:这只会在NavigationLink
活动时被调用,这会发生在currentSelection != nil
struct ContentView: View {
@State var entries = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
@State var currentSelection: Int? = nil
var body: some View {
NavigationView {
ZStack {
EmptyNavigationLink(
destination: { DetailView(entry: $0) },
selection: $currentSelection
)
Form {
ForEach(entries.sorted(), id: \.self) { entry in
NavigationLink(
destination: DetailView(entry: entry),
label: { Text("The number \(entry)") })
}
}
.toolbar {
ToolbarItem(placement: ToolbarItemPlacement.navigationBarLeading) { Button("Add low") {
let newEntry = (entries.min() ?? 1) - 1
entries.insert(newEntry, at: 1)
currentSelection = newEntry
} }
ToolbarItem(placement: ToolbarItemPlacement.navigationBarTrailing) { Button("Add high") {
let newEntry = (entries.max() ?? 50) + 1
entries.append(newEntry)
currentSelection = newEntry
} }
ToolbarItem(placement: ToolbarItemPlacement.bottomBar) {
Text("The current selection is \(String(describing: currentSelection))")
}
}
}
}
}
}
struct DetailView: View {
let entry: Int
var body: some View {
Text("It's a \(entry)!")
}
}
public struct LazyView<Content: View>: View {
private let build: () -> Content
public init(_ build: @autoclosure @escaping () -> Content) {
self.build = build
}
public var body: Content {
build()
}
}
struct EmptyNavigationLink<Destination: View>: View {
let lazyDestination: LazyView<Destination>
let isActive: Binding<Bool>
init<T>(
@ViewBuilder destination: @escaping (T) -> Destination,
selection: Binding<T?>
) {
lazyDestination = LazyView(destination(selection.wrappedValue!))
isActive = .init(
get: { selection.wrappedValue != nil },
set: { isActive in
if !isActive {
selection.wrappedValue = nil
}
}
)
}
var body: some View {
NavigationLink(
destination: lazyDestination,
isActive: isActive,
label: { EmptyView() }
)
}
}
查看有关LazyView的更多信息,它通常有助于NavigationLink
:在实际应用程序中,目标可能是一个巨大的屏幕,当您NavigationLink
在每个单元格中有一个时,SwiftUI 将处理所有这些可能导致滞后
推荐阅读
- java - Java hashmap 在放置新条目时编辑现有条目
- python-3.x - 使用 selenium 和 Python 单击 Flash 按钮
- javascript - 如何在 ng quill 中使用 quill emoji
- html - 在 Wordpress Visual Composer 中使用 CSS 创建响应式全宽 V 形
- java - 如何使构造函数中定义的对象对类的其余部分可见
- python-3.x - Python 异常咳嗽,但堆栈跟踪仍然打印
- puppet - 如何使用 Puppet 管理 ambari 服务器?
- kubernetes - 如何在 Pod 处于终止宽限期时将流量从 Service 发送到 Pod
- bash - awk - 在 unix 中将字符串传递到外部 gfortran 构建的可执行文件
- php - 循环遍历 php 中的 JSON 字符串