SwiftUI如何优雅的管理暗黑or高亮模式?

前言

在2019年的全球开发者大会(WWDC)中,苹果推出了全球果粉最关心的iOS 13操作系统,内置崭新的「暗黑模式」。但是对于大多数开发者来说,在项目创建之后并没有精力来适配,通常手段为直接把暗黑模式关闭。

即:在 Info.plist 文件中,添加 key 为 User Interface Style,类型为 String,value 设置为 Light 即可。

存在即合理,虽然上述配置可以简单粗暴的关闭暗盒模式。但对于夜猫子们来说,并不能带来很友好的体验。So,本文将手把手教学如何管理暗黑模式~

准备思路

实现原理

首先在已经适配的APP当中,会存在跟随系统高亮模式暗黑模式切换的功能。所以,我们首先需要创建一个记录用户上一次选择的状态。对于首次安装的新用户,我们仅需要默认为跟随系统即可。

这里我们使用了 UserDefaults,是用户默认数据库的接口,一般用于存储用户信息、App 设置等基础信息。在用户切换的时候保存,并且更新全局暗黑or明亮模式的状态。

最后,我们需要在用户选择跟随系统时,获取系统当前的状态。

实现代码

获取启动后APP状态的源码
swift 复制代码
import SwiftUI

@main
struct MyDarkModelApp: App {
        
    @StateObject private var appearanceManager = AppearanceManager()
    
    @Environment(\.colorScheme) var colorScheme

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appearanceManager)
                .preferredColorScheme(appearanceManager.isDarkMode ? .dark : .light)
        }
    }
}

class AppearanceManager: ObservableObject {
    
    enum AppearanceColor: Int {
        case iSystem = 0
        case iHight = 1
        case iDark = 2
    }
    
    @Published var isDarkMode: Bool = false
    
    @Published var type: AppearanceColor {
        didSet{
            switch type {
            case .iSystem:
                isDarkMode = (getCurrentInterfaceStyle() == .dark)
            case .iHight:
                isDarkMode = false
            case .iDark:
                isDarkMode = true
            }
            UserDefaults.standard.set(type.rawValue, forKey: "darkMode")
        }
    }
    
    init() {
        
        type = AppearanceColor(rawValue: UserDefaults.standard.integer(forKey: "darkMode")) ?? .iSystem
        switch type {
        case .iSystem:
            isDarkMode = (getCurrentInterfaceStyle() == .dark)
        case .iHight:
            isDarkMode = false
        case .iDark:
            isDarkMode = true
        }
                
    }
    
    func getCurrentInterfaceStyle() -> UIUserInterfaceStyle {
        if #available(iOS 13.0, *) {
            return UIScreen.main.traitCollection.userInterfaceStyle
        } else {
            // 在iOS 12或更早的版本中,默认为明亮模式
            return .light
        }
    }
    
}
用户切换APP状态并更新的源码
scss 复制代码
import SwiftUI

struct ContentView: View {
        
    @EnvironmentObject var appearanceManager: AppearanceManager
    
    var body: some View {
        VStack() {
            List {
                
                switch appearanceManager.type {
                case .iSystem:
                    Text("跟随系统")
                case .iHight:
                    Text("浅色模式")
                case .iDark:
                    Text("暗黑模式")
                }
                
                Text("点我设置明亮模式").foregroundColor(Color("TextColor")).onTapGesture {
                    appearanceManager.type = .iHight
                }
                
                Text("点我设置暗黑模式").foregroundColor(Color("TextColor")).onTapGesture {
                    appearanceManager.type = .iDark
                }
                
                Text("点我设置跟随系统").foregroundColor(Color("TextColor")).onTapGesture {
                    appearanceManager.type = .iSystem
                }
                
                Image("darkImage")
                
            }
        }.onAppear {
            print("isDarkMode----->\(appearanceManager.isDarkMode)")
        }
    }
}

相关拓展

颜色值、以及图片设置

方式1: 使用 Assets.xcassets 适配深色模式 (图片同理)

项目选择->Assets.xcassets->右键->New Color Set->设置名称,如图所示:

方式2: 使用 extension 适配深色模式 (图片同理)

swift 复制代码
extension UIColor {
  convenience init(light: UIColor, dark: UIColor) {
    self.init { traitCollection in
      switch traitCollection.userInterfaceStyle {
      case .light, .unspecified:
        return light
      case .dark:
        return dark
      @unknown default:
        return light
      }
    }
  }
}

extension Color {
  // 再定义一个颜色
  static let defaultBackground = Color(light: .white, dark: .black)
 
  init(light: Color, dark: Color) {
    self.init(UIColor(light: UIColor(light), dark: UIColor(dark)))
  }
}

最终效果

github地址

相关推荐
游戏开发爱好者821 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
黑码哥21 小时前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
2501_915106321 天前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview
2501_915106321 天前
使用 Sniffmaster TCP 抓包和 Wireshark 网络分析
网络协议·tcp/ip·ios·小程序·uni-app·wireshark·iphone
熊猫钓鱼>_>1 天前
移动端开发技术选型报告:三足鼎立时代的开发者指南(2026年2月)
android·人工智能·ios·app·鸿蒙·cpu·移动端
徐同保2 天前
通过ip访问nginx的服务时,被第一个server重定向了,通过设置default_server解决这个问题
ios·iphone
2501_915918412 天前
在 iOS 环境下查看 App 详细信息与文件目录
android·ios·小程序·https·uni-app·iphone·webview
2501_916007472 天前
没有 Mac 用户如何上架 App Store,IPA生成、证书与描述文件管理、跨平台上传
android·macos·ios·小程序·uni-app·iphone·webview
夏幻灵3 天前
HTTPS全面解析:原理、加密机制与证书体
ios·iphone
TheNextByte13 天前
如何在iPhone上恢复已删除的笔记的综合指南
笔记·ios·iphone