EnvironmentObject refresh/hand 关于使用 NavigationLink 的问题
EnvironmentObject refresh/hand over problems using NavigationLink
我目前正在 macOS Catalina 上使用 XCode 11.5 中的 Swift/SwiftUI 为 watchOS 6(独立应用程序)开发一个应用程序。
在用户可以使用我的应用程序之前,需要一个配置过程。由于配置过程由几个不同的视图组成,这些视图依次显示,因此我使用导航 links.
实现了这一点
配置过程完成后,用户应单击按钮 return 进入“主”应用程序(主视图)。为了控制处于同一层级的视图,我的计划是结合使用 EnvironmentObject(据我所知,一旦注入 EnvironmentObject 就会移交给子视图,子视图可以使用 EnvironmentObject)和“控制视图”它控制视图的显示。因此,我遵循了教程:https://blckbirds.com/post/how-to-navigate-between-views-in-swiftui-by-using-an-environmentobject/
这是我的代码:
ContentView.swift
struct ContentView: View {
var body: some View {
ContentViewManager().environmentObject(AppStateControl())
}
}
struct ContentViewManager: View {
@EnvironmentObject var appStateControl: AppStateControl
var body: some View {
VStack {
if(appStateControl.callView == "AppConfig") {
AppConfig()
}
if(appStateControl.callView == "AppMain") {
AppMain()
}
}
}
}
AppStateControl.swift
class AppStateControl: ObservableObject {
@Published var callView: String = "AppConfig"
}
AppConfig.swift
struct AppConfig: View {
@EnvironmentObject var appStateControl: AppStateControl
var body: some View {
VStack {
Text("App Config Main")
NavigationLink(destination: DetailView1().environmentObject(appStateControl)) {
Text("Show Detail View 1")
}
}
}
}
struct DetailView1: View {
@EnvironmentObject var appStateControl: AppStateControl
var body: some View {
VStack {
Text("App Config Detail View 1")
NavigationLink(destination: DetailView2().environmentObject(appStateControl)) {
Text("Show Detail View 2")
}
}
}
}
struct DetailView2: View {
@EnvironmentObject var appStateControl: AppStateControl
var body: some View {
VStack {
Text("App Config Detail View 2")
Button(action: {
self.appStateControl.callView = "AppMain"
}) {
Text("Go to main App")
}
}
}
}
AppMain.swift
struct AppMain: View {
var body: some View {
Text("Main App")
}
}
在我以前的代码版本中(一直没有移交 EnvironmentObject)我遇到了运行时错误(“线程 1:致命错误:找不到类型为 AppStateControl 的 ObservableObject。A AppStateControl 的 View.environmentObject(_:) 作为此视图的祖先可能缺失。) 由 AppConfig.swift 中的第 41 行引起。在互联网上,我读到这可能是 NavigationLink 的一个错误(参见:https://www.hackingwithswift.com/forums/swiftui/environment-object-not-being-inherited-by-child-sometimes-and-app-crashes/269, https://twitter.com/twostraws/status/1146315336578469888)。因此,建议是将 EnvironmentObject 显式传递到 NavigationLink 的目的地(上述实现)。不幸的是,这也不起作用,而是单击 "DetailView2""DetailView2" 中的按钮"Go to main App" 导致视图 "DetailView1" 而不是 "AppMain".
有什么办法解决这个问题吗?对我来说,似乎在通过导航调用的视图中更改 EnvironmentObject link 不会(正确)刷新视图。
提前致谢。
其中一个解决方案是创建一个变量来控制是否显示导航堆栈。
class AppStateControl: ObservableObject {
...
@Published var isDetailActive = false // <- add this
}
然后可以通过设置isActive
参数,用这个变量来控制第一个NavigationLink
。您还需要将 .isDetailLink(false)
添加到所有后续 links.
堆栈中第一个 link:
NavigationLink(destination: DetailView1().environmentObject(appStateControl), isActive: self.$appStateControl.isDetailActive) {
Text("Show Detail View 1")
}
.isDetailLink(false)
所有其他 links:
NavigationLink(destination: DetailView2().environmentObject(appStateControl)) {
Text("Show Detail View 2")
}
.isDetailLink(false)
然后只需将 isDetailActive
设置为 false
以弹出所有 NavigationLinks 并 return 到主视图:
Button(action: {
self.appStateControl.callView = "AppMain"
self.appStateControl.isDetailActive = false // <- add this
}) {
Text("Go to main App")
}
我目前正在 macOS Catalina 上使用 XCode 11.5 中的 Swift/SwiftUI 为 watchOS 6(独立应用程序)开发一个应用程序。
在用户可以使用我的应用程序之前,需要一个配置过程。由于配置过程由几个不同的视图组成,这些视图依次显示,因此我使用导航 links.
实现了这一点配置过程完成后,用户应单击按钮 return 进入“主”应用程序(主视图)。为了控制处于同一层级的视图,我的计划是结合使用 EnvironmentObject(据我所知,一旦注入 EnvironmentObject 就会移交给子视图,子视图可以使用 EnvironmentObject)和“控制视图”它控制视图的显示。因此,我遵循了教程:https://blckbirds.com/post/how-to-navigate-between-views-in-swiftui-by-using-an-environmentobject/
这是我的代码:
ContentView.swift
struct ContentView: View {
var body: some View {
ContentViewManager().environmentObject(AppStateControl())
}
}
struct ContentViewManager: View {
@EnvironmentObject var appStateControl: AppStateControl
var body: some View {
VStack {
if(appStateControl.callView == "AppConfig") {
AppConfig()
}
if(appStateControl.callView == "AppMain") {
AppMain()
}
}
}
}
AppStateControl.swift
class AppStateControl: ObservableObject {
@Published var callView: String = "AppConfig"
}
AppConfig.swift
struct AppConfig: View {
@EnvironmentObject var appStateControl: AppStateControl
var body: some View {
VStack {
Text("App Config Main")
NavigationLink(destination: DetailView1().environmentObject(appStateControl)) {
Text("Show Detail View 1")
}
}
}
}
struct DetailView1: View {
@EnvironmentObject var appStateControl: AppStateControl
var body: some View {
VStack {
Text("App Config Detail View 1")
NavigationLink(destination: DetailView2().environmentObject(appStateControl)) {
Text("Show Detail View 2")
}
}
}
}
struct DetailView2: View {
@EnvironmentObject var appStateControl: AppStateControl
var body: some View {
VStack {
Text("App Config Detail View 2")
Button(action: {
self.appStateControl.callView = "AppMain"
}) {
Text("Go to main App")
}
}
}
}
AppMain.swift
struct AppMain: View {
var body: some View {
Text("Main App")
}
}
在我以前的代码版本中(一直没有移交 EnvironmentObject)我遇到了运行时错误(“线程 1:致命错误:找不到类型为 AppStateControl 的 ObservableObject。A AppStateControl 的 View.environmentObject(_:) 作为此视图的祖先可能缺失。) 由 AppConfig.swift 中的第 41 行引起。在互联网上,我读到这可能是 NavigationLink 的一个错误(参见:https://www.hackingwithswift.com/forums/swiftui/environment-object-not-being-inherited-by-child-sometimes-and-app-crashes/269, https://twitter.com/twostraws/status/1146315336578469888)。因此,建议是将 EnvironmentObject 显式传递到 NavigationLink 的目的地(上述实现)。不幸的是,这也不起作用,而是单击 "DetailView2""DetailView2" 中的按钮"Go to main App" 导致视图 "DetailView1" 而不是 "AppMain".
有什么办法解决这个问题吗?对我来说,似乎在通过导航调用的视图中更改 EnvironmentObject link 不会(正确)刷新视图。
提前致谢。
其中一个解决方案是创建一个变量来控制是否显示导航堆栈。
class AppStateControl: ObservableObject {
...
@Published var isDetailActive = false // <- add this
}
然后可以通过设置isActive
参数,用这个变量来控制第一个NavigationLink
。您还需要将 .isDetailLink(false)
添加到所有后续 links.
堆栈中第一个 link:
NavigationLink(destination: DetailView1().environmentObject(appStateControl), isActive: self.$appStateControl.isDetailActive) {
Text("Show Detail View 1")
}
.isDetailLink(false)
所有其他 links:
NavigationLink(destination: DetailView2().environmentObject(appStateControl)) {
Text("Show Detail View 2")
}
.isDetailLink(false)
然后只需将 isDetailActive
设置为 false
以弹出所有 NavigationLinks 并 return 到主视图:
Button(action: {
self.appStateControl.callView = "AppMain"
self.appStateControl.isDetailActive = false // <- add this
}) {
Text("Go to main App")
}