【问题标题】:How to provide a ‘System’ appearance choice in SwiftUI?如何在 SwiftUI 中提供“系统”外观选择?
【发布时间】:2020-10-31 07:55:50
【问题描述】:

主要问题

抱歉,标题太长了。我正在尝试弄清楚如何为用户提供将应用程序的 ColorScheme 设置为“系统”的选择。

同样,让应用程序默认为系统的暗模式/亮模式。我知道 UIKit 有办法将样式设置为 .unspecified 但我不确定如何在 SwiftUI 中访问它。

我已经尝试将 .preferredColor() 设置为 nil,它有点工作,但有时它没有。我是 Swift 管理状态的新手,所以我肯定做错了什么。

附带问题:
当我将.preferredColor() 设置为.dark 时,我的模态设置表没有更新?它始终保持系统颜色。我在 ...App.swift 文件中的 ContentView() 上触发了 .preferredColor()

更新

我也解决了我的附带问题,只需将.preferredColor() 添加到模态表即可。这并不理想,但确实有效。但是我仍然无法弄清楚如何在 SwiftUI 中设置 .system 首选项

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    我最终找到了解决这个问题的两种方法。第一个是jinjie 发现的,另一个是我发现的。两种解决方案都可以是viewed here - repo。由rizwankce创建。

    解决方案

    我最终做的是使用包Introspect 从我使用ViewModifier 的主视图中获取UIViewController

    ViewModifier 中,我只使用了.introspectViewController,这给了我UIViewController,这样我就可以像这样设置UIViewController.overrideUserInterfaceStyle = .unspecified。然后我只是根据下面没有看到的Picker 有条件地执行此操作。 ⤵

    
    /// All themes
    enum Themes: String {
        case Dark
        case Light
        case System
    }
    
    // MARK: - Theme Switch
    
    struct ThemeSwitch: ViewModifier {
        let appStorage: String
    
        func body(content: Content) -> some View {
            content
                .introspectViewController { UIViewController in
                    switch appStorage {
                    case Themes.System.rawValue: UIViewController.overrideUserInterfaceStyle = .unspecified
                    case Themes.Dark.rawValue: UIViewController.overrideUserInterfaceStyle = .dark
                    case Themes.Light.rawValue: UIViewController.overrideUserInterfaceStyle = .light
                    default: UIViewController.overrideUserInterfaceStyle = .unspecified
                    }
                }
        }
    }
    
    // MARK: - Extensions
    
    extension View {
        func themeSwitch(appStorage: String) -> some View {
            modifier(ThemeSwitch(appStorage: appStorage))
        }
    }
    
    

    我只是将所需主题作为字符串存储到 @State 对象中,该对象还更新了 @AppStorage 对象,因此无论如何应用程序始终可以选择。

    您不必使用 Introspect,而是可以创建自己的包装器,但我已经安装了这个包,所以我想为什么不这样做。

    替代解决方案

    另一种解决方案是制作视图修改器并有条件地显示修改后的视图。条件基于ColorScheme 类型的可选数组、字典等。如果它不是 nil,它要么解开可选项,要么只显示未修改的视图。你可以在 repo 中找到它。上面提到的已关闭问题或拉取请求。

    希望将来 Apple 会提供一种本地方式来实现这一点,但现在可以做到!如果出现更好的情况,我会尝试在将来更新此答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-09
      • 2011-11-28
      相关资源
      最近更新 更多