使用 SwiftUI 和 SceneDelegate 生命周期的系统范围
我使用in the answer by Mojtaba Hosseini 的答案中提供的提示在 SwiftUI(具有 AppDelegate 生命周期的应用程序)中制作了我自己的版本。我还没有考虑使用 iOS14 的 @main 代替 SceneDelegate。
这里是 GitHub 存储库的链接。该示例具有浅色、深色和自动选择器,可更改整个应用的设置。
我加倍努力使其可本地化!
GitHub repo
我需要访问SceneDelegate,并且我使用与 Mustapha 相同的代码并添加了一点点,当应用程序启动时,我需要读取存储在 UserDefaults 或 @AppStorage 等中的设置。
因此,我在启动时再次更新 UI:
private(set) static var shared: SceneDelegate?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
Self.shared = self
// this is for when the app starts - read from the user defaults
updateUserInterfaceStyle()
}
函数updateUserInterfaceStyle() 将在SceneDelegate 中。
我在这里使用了 UserDefaults 的扩展使其与 iOS13 兼容(感谢twanni!):
func updateUserInterfaceStyle() {
DispatchQueue.main.async {
switch UserDefaults.userInterfaceStyle {
case 0:
self.window?.overrideUserInterfaceStyle = .unspecified
case 1:
self.window?.overrideUserInterfaceStyle = .light
case 2:
self.window?.overrideUserInterfaceStyle = .dark
default:
self.window?.overrideUserInterfaceStyle = .unspecified
}
}
}
这与apple documentation for UIUserInterfaceStyle一致
使用选择器意味着我需要对我的三个案例进行迭代,因此我创建了一个符合可识别且类型为 LocalizedStringKey 的枚举用于本地化:
// check LocalizedStringKey instead of string for localisation!
enum Appearance: LocalizedStringKey, CaseIterable, Identifiable {
case light
case dark
case automatic
var id: String { UUID().uuidString }
}
这是选择器的完整代码:
struct AppearanceSelectionPicker: View {
@Environment(\.colorScheme) var colorScheme
@State private var selectedAppearance = Appearance.automatic
var body: some View {
HStack {
Text("Appearance")
.padding()
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
Picker(selection: $selectedAppearance, label: Text("Appearance")) {
ForEach(Appearance.allCases) { appearance in
Text(appearance.rawValue)
.tag(appearance)
}
}
.pickerStyle(WheelPickerStyle())
.frame(width: 150, height: 50, alignment: .center)
.padding()
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}
.padding()
.onChange(of: selectedAppearance, perform: { value in
print("changed to ", value)
switch value {
case .automatic:
UserDefaults.userInterfaceStyle = 0
SceneDelegate.shared?.window?.overrideUserInterfaceStyle = .unspecified
case .light:
UserDefaults.userInterfaceStyle = 1
SceneDelegate.shared?.window?.overrideUserInterfaceStyle = .light
case .dark:
UserDefaults.userInterfaceStyle = 2
SceneDelegate.shared?.window?.overrideUserInterfaceStyle = .dark
}
})
.onAppear {
print(colorScheme)
print("UserDefaults.userInterfaceStyle",UserDefaults.userInterfaceStyle)
switch UserDefaults.userInterfaceStyle {
case 0:
selectedAppearance = .automatic
case 1:
selectedAppearance = .light
case 2:
selectedAppearance = .dark
default:
selectedAppearance = .automatic
}
}
}
}
当用户进入该设置视图时,代码onAppear 用于将滚轮设置为正确的值。每次移动滚轮时,通过 .onChange 修饰符,用户默认值都会更新,并且应用会通过引用 SceneDelegate 更改所有视图的设置。
(如果有兴趣,可以在 GH 回购中提供 gif。)