(使用Xcode 11 beta 7)是否可以访问祖先的自定义EnvironmentObject?如果可以,怎么办?并使用无限深度?
比方说,我们在导航中有很多深度层次,例如
UIScene-> MainView-> TabView(其中包含一个标签:)-> SettingsView-> AboutView-> AppVersionView
开始将MainView视为深度级别1,而不考虑TabView,我们的AppVersionView在导航堆栈中处于深度级别4。
假设我们需要使用一些自定义依赖项,例如RESTClient或AppVersionView中的任何内容。这种依赖是无关紧要的。与此相关的是,我们的SceneDelegate类实例化了这种依赖关系,并且深度为1的视图(MainView)将该视图声明为@EnvirontmentObject
以便将其注入。
我当前的解决方案是MainView通过将其向下注入到堆栈中的下一个视图SettingsView来“手动”转发它。然后在SettingsView中,我再次手动转发它。
这是一个简化的示例,实际上我在my SwiftUI app的整个使用过程中都具有多个依赖关系,并且在整个导航堆栈中都有不同的层次。
我的想法是,是否有可能以某种方式读取/访问这些注入的EnvironmentObject?在最佳情况下,从任何较早的祖先递归地进行。
如果我正确理解了SwiftUI,那么ViewModifiers就是这种情况。如果将ViewModifier .foregroundColor(.red)
添加到MainView,则应将其作为系统范围的默认颜色通过整个应用程序传递(继承)。
我希望使用自定义的EnvironmentObject可以完成同样的事情。而且我知道我们可以像EnvironmentValues
这样的视图访问预定义的(非自定义)this example from Mecid's great blog:struct ButtonsView: View {
@Environment(\.sizeCategory) var sizeCategory
var body: some View {
Group {
if sizeCategory == .accessibilityExtraExtraExtraLarge {
VStack {
buttons
}
} else {
HStack {
buttons
}
}
}
}
}
答案 0 :(得分:2)
使用environmentObject
修饰符放入环境中的对象通过TabView
和NavigationView
向下传递到所有后代视图的视图层次结构中。您无需做任何特殊的事情(例如手动转发)就可以做到这一点。
在此示例中,在SceneDelegate
中,我将使用MainView
修饰符将模型对象存储在environmentObject
的环境中。模型对象具有appVersion
字符串属性。我将使用@EnvironmentObject
中的AppVersionView
属性访问模型对象,并使用模型的appVersion
来填充Text
子视图。
代码如下:
import UIKit
import SwiftUI
class Model: ObservableObject {
@Published var appVersion: String = "version-1"
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let model = Model()
let contentView = MainView().environmentObject(model)
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
struct MainView: View {
var body: some View {
TabView {
NavigationView {
SettingsView()
}
.tabItem {
Image(systemName: "gear")
Text("Settings") }
}
}
}
struct SettingsView: View {
var body: some View {
List {
NavigationLink("About", destination: AboutView())
}
}
}
struct AboutView: View {
var body: some View {
List {
NavigationLink("App Version", destination: AppVersionView())
}
}
}
struct AppVersionView: View {
@EnvironmentObject var model: Model
var body: some View {
VStack {
Text("App Version View")
Text(model.appVersion)
}
.padding()
.border(Color.black)
}
}