SwiftUI 中某些环境自动更新背后的奥秘

     2023-02-24     79

关键词:

【中文标题】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、horizo​​ntalSizeClass、verticalSizeClass,都默认应用到WindowGroup

侧的Views

谜团解开!


【讨论】:

SwiftUI 环境对象未更新

】SwiftUI环境对象未更新【英文标题】:SwiftUIEnvironmentObjectNotGettingUpdated【发布时间】:2020-10-2519:46:52【问题描述】:我认为是这样的情况,指定为环境对象的类中的@Published属性会自动更新到我将环境对象传递给的所有子视图,... 查看详情

SwiftUI - 环境对象未更新 UI

】SwiftUI-环境对象未更新UI【英文标题】:SwiftUI-EnvironmentObjectNotUpdatingUI【发布时间】:2019-11-1215:58:07【问题描述】:我的应用有一个按钮,可以生成绿色或红色背景。用户一次又一次地按下按钮以生成绿色或红色,并将结果记录... 查看详情

选择器更改时,SwiftUI 环境变量中的字符串插值未更新

】选择器更改时,SwiftUI环境变量中的字符串插值未更新【英文标题】:StringInterpolationNotUpdatinginSwiftUIEnvironmentVariableWhenChangedbyPicker【发布时间】:2019-11-0100:11:43【问题描述】:我有一个消息示例列表,这些示例使用字符串插值使... 查看详情

如何使用@EnvironmentObject 在 SwiftUI 中自动填充和更新列表?

】如何使用@EnvironmentObject在SwiftUI中自动填充和更新列表?【英文标题】:Howtouse@EnvironmentObjecttopopulateandupdatelistautomaticallyinSwiftUI?【发布时间】:2019-12-3121:45:18【问题描述】:正如标题所说,我正在尝试使用一个@EnvironmentObject来... 查看详情

@aspect注解背后的奥秘--上(代码片段)

@Aspect注解背后的奥秘--上引言aop的原始时代ProxyFactory实现思路AspectJProxyFactory的实现思路1.切面元数据解析过程2.InstantiationModelAwarePointcutAdvisorImpl获取advice3.AopUtils筛选能够应用到当前目标对象上的advisors4.AspectJProxyUtils添加一个Ex... 查看详情

文智背后的奥秘系列篇——情感分类

版权声明:本文由文智原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/92来源:腾云阁 https://www.qcloud.com/community 情感分类是对带有感情色彩的主观性文本进行分析、推理的过程,即分析对... 查看详情

swiftui不借助scrollviewreader和scrollviewproxy实现list自动滚动到底部

功能需求从SwiftUI2.0开始(iOS14.0+,MacOS11.0+),对于List的滚动操作我们有了更多的选择。借助于ScrollViewReader和ScrollViewProxy两枚利器,我们可以轻松读取和设置List的滚动位置。但是如何在早期的SwiftUI(1.0)中实现该功能呢?如上所示,... 查看详情

从 SwiftUI 中的列表中删除绑定

】从SwiftUI中的列表中删除绑定【英文标题】:DeleteaBindingfromalistinSwiftUI【发布时间】:2021-10-2802:13:49【问题描述】:我试图从Swift和SwiftUI的列表中简单地删除一个元素。如果没有在ForEach循环中绑定某些东西,它确实会被删除。... 查看详情

SwiftUI 如何使用带有自定义对象数组的 Dict 进行 ForEach 自动更新

】SwiftUI如何使用带有自定义对象数组的Dict进行ForEach自动更新【英文标题】:SwiftUIHowtomakeForEachwithDictwitharrayofcustomobjectsautoupdate【发布时间】:2021-08-2601:30:59【问题描述】:我有一个包含自定义类数组的字典,定义如下:varcoupons... 查看详情

文智背后的奥秘系列篇——结构化抽取平台

版权声明:本文由文智原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/91来源:腾云阁 https://www.qcloud.com/community 随着大数据时代的到来,一个大规模生成、分享、处理以及应用数据的时代... 查看详情

在 SwiftUI 中播放音频时无法更新行颜色

】在SwiftUI中播放音频时无法更新行颜色【英文标题】:Cannotupdaterowcolorwhileplayingaudio,inSwiftUI【发布时间】:2021-04-2909:01:49【问题描述】:在使用SwiftUI开发iOS应用程序时,我面临以下情况。我已经设置了一个自定义环境键。这是Sc... 查看详情

xcode如何在预览(preview)调试中避免与swiftui正常运行时环境不一致导致的崩溃

...有时候,我们需要在Xcode预览(Preview)中快速查看或测试SwiftUI视图的界面和功能,但遗憾的是预览和实际运行的环境从来都不会完全一样。某些情况下,实际运行环境中App的初始化代码很难在Preview环境中执行。所以,我们在Xcod... 查看详情

xcode如何在预览(preview)调试中避免与swiftui正常运行时环境不一致导致的崩溃

...有时候,我们需要在Xcode预览(Preview)中快速查看或测试SwiftUI视图的界面和功能,但遗憾的是预览和实际运行的环境从来都不会完全一样。某些情况下,实际运行环境中App的初始化代码很难在Preview环境中执行。所以,我们在Xcod... 查看详情

在 Swiftui 中如何通过旋转到横向自动关闭模态

】在Swiftui中如何通过旋转到横向自动关闭模态【英文标题】:InSwiftuiHowtoautomaticallyclosemodalwithrotationtolandscape【发布时间】:2020-07-0818:30:05【问题描述】:我目前使用基于此代码的景观环境对象-https://***.com/a/58503841/412154在我看来... 查看详情

SwiftUI iOS 14 |在 HStack 中自动展开文本框和内容

】SwiftUIiOS14|在HStack中自动展开文本框和内容【英文标题】:SwiftUIiOS14|autoexpandtextboxandcontentaroundinHStack【发布时间】:2021-02-2521:36:02【问题描述】:iOS14更新后,文本框不再展开,箭头不再适应不同长度的文本。如gif所示,文本宽... 查看详情

在 SwiftUI 中更改方向时更新 UI

】在SwiftUI中更改方向时更新UI【英文标题】:UpdateUIwhenorientationischanginginSwiftUI【发布时间】:2021-01-0520:09:55【问题描述】:我已经开始学习SwiftUI。当方向改变时,我尝试更新UI。我在视图中添加了@Environment(\\.horizontalSizeClass)varsiz... 查看详情

swiftuiapp入口生命周期管理方式(lifecycle)

...理解为用来做全局状态管理的关键字,如果值发生变化,SwiftUI会更新视图中依赖于该值的任何部分。例如,如果用户更改了外观设置,则在上面的示例中可能会发生这种情况。您可以使用此属性包装器读取(但不能设置)环境... 查看详情

以后如何在环境中更新 ManagedObjectContext

...布时间】:2020-10-2905:47:59【问题描述】:我有一个基本的SwiftUI应用程序,它在应用程序启动时初始化一个基于NSPersistentCloudKitContainer的持久堆栈,并将viewContext注入环境并将其传递给我的应用程序的所 查看详情