首先添加多语言文件 Localizable.xcstrings
如果希望在 iOS 17 之前使用 @EnvironmentObject
,但不想在 ContentView
中手动传递 languageState
,可以在 WindowGroup
上直接使用 .environmentObject
来设置。这样可以确保在整个应用中都能访问到 languageState
。以下是如何实现的示例:
1. 更新 LanguageState
类
首先,保持之前的 LanguageState
类,它会在启动时从 UserDefaults
加载语言设置,并在语言更改时保存到 UserDefaults
中:
import Combine
import SwiftUI
class LanguageState: ObservableObject {
@Published var localeIdentifier: String {
didSet {
saveLanguage() // 每次语言改变时保存
}
}
init() {
localeIdentifier = UserDefaults.standard.string(forKey: "selectedLanguage") ?? Locale.current.identifier
}
func switchLanguage(to identifier: String) {
localeIdentifier = identifier
}
private func saveLanguage() {
UserDefaults.standard.set(localeIdentifier, forKey: "selectedLanguage")
}
}
2. 在应用入口设置 @EnvironmentObject
在应用的入口文件中,直接将 languageState
作为环境对象传递给 WindowGroup
,而不是通过构造函数传递给 ContentView
:
@main
struct MyApp: App {
@StateObject private var languageState = LanguageState()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(languageState) // 在这里设置环境对象
.environment(\.locale, Locale(identifier: languageState.localeIdentifier)) // 设置语言环境
}
}
}
3. 在 LanguageChangeView
中使用 @EnvironmentObject
在 LanguageChangeView
中使用 @EnvironmentObject
直接访问 languageState
:
struct LanguageChangeView: View {
@EnvironmentObject var languageState: LanguageState
@State private var selectedLanguage: String = ""
let languages = ["zh-Hans", "en"]
var body: some View {
List(languages, id: \.self) { language in
HStack {
Text(language == "zh-Hans" ? "简体中文" : "English")
Spacer()
if language == selectedLanguage {
Image(systemName: "checkmark")
.foregroundColor(.black)
}
}
.contentShape(Rectangle())
.onTapGesture {
selectedLanguage = language
languageState.switchLanguage(to: language)
}
}
.navigationTitle("语言切换")
.onAppear {
selectedLanguage = languageState.localeIdentifier
}
}
}
struct LanguageChangeView_Previews: PreviewProvider {
static var previews: some View {
// 创建一个测试用的 LanguageState 对象并传入预览
LanguageChangeView()
.environmentObject(LanguageState())
}
}
总结
- 使用
@EnvironmentObject
:在WindowGroup
中直接设置环境对象,确保整个应用都可以访问。 - 简化传递:不需要在每个视图中手动传递
languageState
,使代码更加简洁。
这样,当你在应用中切换语言时,languageState
会自动更新,并且所有使用了 @EnvironmentObject
的视图会相应地更新。