[英]SwiftUI : possible to access ancestor custom `@EnvironmentObject`? If yes, how?
(Using Xcode 11 beta 7) is it possible to access custom EnvironmentObject of ancestors? (使用Xcode 11 beta 7)是否可以访问祖先的自定义EnvironmentObject? If so how?
如果可以,怎么办? And using unlimited depth?
并使用无限深度?
Let's say we have many levels of depth in our navigation, eg 假设我们在导航中有很多深度层次,例如
UIScene -> MainView -> TabView (which contains a tab:) -> SettingsView -> AboutView -> AppVersionView UIScene-> MainView-> TabView(包含一个选项卡:)-> SettingsView-> AboutView-> AppVersionView
Starting counting MainView as depth level 1, and not coubting TabView, our AppVersionView is at depth level 4 in our navigationstack. 开始将MainView视为深度级别1,而不考虑TabView,我们的AppVersionView在导航堆栈中处于深度级别4。
Let's say we need to use some custom dependency, eg a RESTClient or whatever in AppVersionView. 假设我们需要使用一些自定义的依赖项,例如RESTClient或AppVersionView中的任何内容。 What this depedency is is irrelevant.
这种依赖是无关紧要的。 What is relevant is that our SceneDelegate class instantiates this depedency and the view at depth 1 (MainView) declares it as an
@EnvirontmentObject
to get it injected. 与此相关的是,我们的SceneDelegate类实例化了此依赖关系,深度为1的视图(MainView)将其声明为
@EnvirontmentObject
进行注入。
My current solution is that MainView "manually" forwards it by injecting it down to the next view in the stack, the SettingsView. 我当前的解决方案是MainView通过将其向下注入堆栈中的下一个视图SettingsView来“手动”转发。 And in the SettingsView I manually forward it again etc.
在SettingsView中,我再次手动转发它,等等。
This is a simplified example, in fact I have multiple dependencies throughout my SwiftUI app , being used and different layers throughout the navigation stack. 这是一个简化的示例,实际上,我在整个SwiftUI应用程序中都存在多个依赖关系,正在使用它们,并且在整个导航堆栈中具有不同的层次。
My thought was if it is possible to read/access these injected EnvironmentObjects somehow? 我的想法是,是否有可能以某种方式读取/访问这些注入的EnvironmentObject? In best case scenario recursively from any earlier ancestor.
在最佳情况下,从任何较早的祖先递归地进行。
If I have understood SwiftUI correctly, that is the case with ViewModifiers. 如果我正确理解了SwiftUI,那么ViewModifiers就是这种情况。 If I add the ViewModifier
.foregroundColor(.red)
to MainView, it should be passed as a system wide default color through out the app (inherited). 如果将ViewModifier
.foregroundColor(.red)
.red .foregroundColor(.red)
添加到MainView,则应将其作为系统范围的默认颜色通过整个应用程序传递(继承)。
I was hoping the same thing could be done with custom EnvironmentObject. 我希望使用自定义的EnvironmentObject可以完成同样的事情。 And I know we can access predefined (non-custom) EnvironmentValues , in our views like this example from Mecid's great blog:
而且我知道我们可以从Mecid的出色博客的示例中访问预定义(非自定义)的EnvironmentValues :
struct ButtonsView: View {
@Environment(\.sizeCategory) var sizeCategory
var body: some View {
Group {
if sizeCategory == .accessibilityExtraExtraExtraLarge {
VStack {
buttons
}
} else {
HStack {
buttons
}
}
}
}
} }
An object put into the environment using the environmentObject
modifier is passed down the view hierarchy, through TabView
and NavigationView
, to all descendant views. 使用
environmentObject
修饰符放入环境中的对象通过TabView
和NavigationView
向下传递到所有后代视图的视图层次结构中。 You don't have to do anything special (like manually forwarding it) to make this happen. 您不必做任何特殊的事情(例如手动转发它)就可以做到这一点。
In this example, in SceneDelegate
, I'll store a model object in the environment of the MainView
using the environmentObject
modifier. 在此示例中,在
SceneDelegate
,我将使用environmentObject
修饰符将模型对象存储在MainView
的environmentObject
。 The model object has an appVersion
string property. 模型对象具有
appVersion
字符串属性。 I'll access the model object using the @EnvironmentObject
attribute in AppVersionView
and use the model's appVersion
to populate a Text
subview. 我将使用访问模型对象
@EnvironmentObject
在属性AppVersionView
和使用模型的appVersion
来填充Text
子视图。
Here's the code: 这是代码:
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)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.