swiftui - NavigationView 总是创建一个新视图
问题描述
我创建了 aNavigationView
并且它可以工作,但是每次单击 aNavigationLink
时,SwiftUI 都会重新创建目标视图并重置其中的每个属性。看这个例子:
struct NavView: View {
@State var selectionIndex: Int? = nil
let views = [
DestinationView(viewNumber: 1),
DestinationView(viewNumber: 2),
DestinationView(viewNumber: 3)
]
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: self.views[0], tag: 0, selection: $selectionIndex) {
Text("View 1")
}
NavigationLink(destination: self.views[1], tag: 1, selection: $selectionIndex) {
Text("View 2")
}
NavigationLink(destination: self.views[2], tag: 0, selection: $selectionIndex) {
Text("View 3")
}
}
self.views[0]
}
}
}
struct DestinationView: View {
@State var viewNumber: Int
@State var count = 0
var body: some View {
VStack {
Text("View \(self.viewNumber)")
.font(.largeTitle)
Text("Count: \(self.count)")
Button(action: {
self.count += 1
}) {
Text("Increase counter")
}
}
}
}
在此示例中,例如单击 View1 链接将打开 View 1。按下按钮会增加 count 属性。如果您然后单击 View2 按钮,然后返回 View1 按钮,则 count 属性将再次为零。
编辑
body
正如评论中所建议的那样,我还尝试不存储视图并直接在其中创建它们。也不起作用:(
struct NavView: View {
@State var selectionIndex: Int? = nil
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DestinationView(viewNumber: 1), tag: 0, selection: $selectionIndex) {
Text("View 1")
}
NavigationLink(destination: DestinationView(viewNumber: 2), tag: 1, selection: $selectionIndex) {
Text("View 2")
}
NavigationLink(destination: DestinationView(viewNumber: 3), tag: 2, selection: $selectionIndex) {
Text("View 3")
}
}
}
}
}
编辑 2
我也尝试在全球范围内存储视图,我也尝试过有和没有tag:
和selection:
解决方案
您的代码中的问题是,每当我们导航到 DestinationView 时,默认情况下每次将计数初始化为 0,所以技巧是我们必须更新计数值并将其保存在 NavView 中的某个位置。
首先,您必须创建DestinationViewModel
以跟踪更新的计数值,如下所示
class DestinationViewModel: ObservableObject {
@Published var viewNumber: Int
@Published var count: Int
init(_ viewNumber: Int, count: Int) {
self.viewNumber = viewNumber
self.count = count
}
}
然后你可以访问你DestinationViewModel
的DestinationView
struct DestinationView: View {
@EnvironmentObject var viewModel: DestinationViewModel
var body: some View {
VStack {
Text("View \(viewModel.viewNumber)")
.font(.largeTitle)
Text("Count: \(viewModel.count)")
Button(action: {
self.viewModel.count += 1
}) {
Text("Increase counter")
}
}
}
}
以下是您的更新NavView
class DestinationViewModelContainer: ObservableObject {
@Published var viewModels: [DestinationViewModel]
init(_ viewModels: [DestinationViewModel]) {
self.viewModels = viewModels
}
}
struct NavView: View {
@EnvironmentObject var viewModelContainer: DestinationViewModelContainer
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DestinationView().environmentObject(viewModelContainer.viewModels[0])) {
Text("View 1")
}
NavigationLink(destination: DestinationView().environmentObject(viewModelContainer.viewModels[1])) {
Text("View 2")
}
NavigationLink(destination: DestinationView().environmentObject(viewModelContainer.viewModels[2])) {
Text("View 3")
}
}
}
}
}
在这里你可以NavView
从下面的代码中调用你的
let contentView = NavView().environmentObject(DestinationViewModelContainer([DestinationViewModel(1, count: 0), DestinationViewModel(2, count: 0),DestinationViewModel(3, count: 0)]))
希望它会帮助你。
推荐阅读
- javascript - 如何禁用 Bootstrap Datepicker 的转义键?
- javascript - 如何使用 Cleave js/Vue-Cleave 作为指令在 Vuejs 中输入元素?
- c# - unity2d 游戏中的玩家运动无法正常工作
- vue.js - 如何创建两个不同值的Vue-Router?
- css - 设置 CSS 字体时的 HTML 按钮元素高度:继承
- javascript - 无论如何将数组名称转换为字符串?
- javascript - React Native TypeError:无法读取未定义的属性'createClient'
- wordpress - 我想在 Google Cloud 中托管 wordpress 网站。我现有的 G Suite 邮件会照常工作吗?
- java - 两个参数列表中的 JPQL 条件
- php - 如何在 Laravel Eloquent 中实现嵌套的 If 语句?