SwiftUI 中某些环境自动更新背后的奥秘
Posted
技术标签:
【中文标题】SwiftUI 中某些环境自动更新背后的奥秘【英文标题】:The Mystery behind auto update of some Environment in SwiftUI 【发布时间】:2021-03-29 17:23:50 【问题描述】:我可以使用环境修改器轻松更改视图级别中名为 backgroundColor 的自定义环境!像这样下来的代码:
CustomView()
.environment(\.backgroundColor, toggleCustomViewBackgroundColor ? Color.yellow : Color.green)
如您所见,我可以为 CustomView() 更改/更新@Environment(\.backgroundColor) var backgroundColor: Color
。而且效果很好!
那么我如何在整个项目中更改/更新@Environment(\.backgroundColor) var backgroundColor: Color
?
也许你们中的一些人会说这样做:
ContentView()
.environment(\.backgroundColor, toggleAppBackgroundColor ? Color.yellow : Color.green)
这将是在整个 Project 中更新 @Environment(\.backgroundColor) var backgroundColor: Color
的一种方式,但正如我们现在 colorScheme 那样 不 以这种方式工作!它会根据设备当前的实际暗/亮模式在整个项目中进行自我更新,而不使用环境修改器!
让我说一下发生了什么! colorScheme 可以在不使用环境修饰符的情况下自行更新,当然它有一个逻辑可以使更新发生在整个项目中,为了让我们的一切变得简单,我制作了一个按钮,它播放一个逻辑,可以在整个项目中更新 @Environment(\.backgroundColor) var backgroundColor: Color
而不使用环境修饰符,所以 如何 colorScheme 可以自我更新,我也想为我的 Custom-Environment 提供该功能。例如,点击该按钮 backgroundColor-Environment 会明白现在是时候在整个项目中更新 backgroundColor 了。每个子视图都会注意到新的更新!比如colorScheme。
private struct BackgroundColorKey: EnvironmentKey
static var defaultValue = Color.yellow
extension EnvironmentValues
var backgroundColor: Color
get return self[BackgroundColorKey.self]
set(newValue) self[BackgroundColorKey.self] = newValue
struct CustomView: View
@Environment(\.backgroundColor) var backgroundColor: Color
var body: some View
VStack
Text("Hello world!")
.background(backgroundColor)
.padding()
import SwiftUI
struct ContentView: View
@Environment(\.backgroundColor) var backgroundColor: Color
@State private var toggleCustomViewBackgroundColor: Bool = Bool()
var body: some View
Button("Update backgroundColor in App Level!")
// Update backgroundColor in App Level, witout using environment modifier!!!
.padding()
Text("Hello world!")
.background(backgroundColor)
.padding()
Button("toggle backgroundColor in View Level!")
toggleCustomViewBackgroundColor.toggle()
.padding()
CustomView()
.environment(\.backgroundColor, toggleCustomViewBackgroundColor ? Color.yellow : Color.green)
【问题讨论】:
【参考方案1】:据我们所知,我的问题是寻找在不使用 环境修饰符的情况下更新自定义环境的答案比如 colorScheme。
这就是我认为 ColorScheme Environment 应该发生的事情!默认情况下,Apple 为我们创建的每个 SwiftUI 项目都做了类似这样的代码!但是环境修饰符应用了Undercover! 我们看不到它!我已经证明了这一点!
ContentView()
.environment(\.colorScheme, colorSchemeUpdater())
我的理论的证明:
如果您尝试在 App 中阅读 colorScheme,它不会更新自己以获得实际正确的值!因为在应用中 environment modifier for colorScheme 没有应用以获得新的更新!现在就自己试试这个代码吧!它不会显示或更新 colorScheme 的真实值!
import SwiftUI
@main
struct EnvironmentApp: App
@Environment(\.colorScheme) var colorScheme
var body: some Scene
WindowGroup
Text(colorScheme == .dark ? "dark" : "light")
ContentView()
但是,如果您尝试使用此代码,它会起作用并且会显示正确的价值!甚至我们也没有在 ContentView() 上为 colorScheme 明确使用 环境修饰符,因为 Apple 为我们完成了它卧底!
struct ContentView: View
@Environment(\.colorScheme) var colorScheme
var body: some View
Text(colorScheme == .dark ? "dark" : "light")
其他环境也有类似scenePhase、horizontalSizeClass、verticalSizeClass,都默认应用到WindowGroup
侧的Views谜团解开!
【讨论】:
以上是关于SwiftUI 中某些环境自动更新背后的奥秘的主要内容,如果未能解决你的问题,请参考以下文章
如何使用@EnvironmentObject 在 SwiftUI 中自动填充和更新列表?
新版Azure Automation Account 浅析 --- 更新Powershell模块和创建Runbook
SwiftUI App入口生命周期管理方式(Life Cycle)