|
|
# 语言切换Bug修复报告
|
|
|
|
|
|
## 问题描述
|
|
|
|
|
|
用户报告了一个语言切换的bug:"设置语言有bug,语言更改后其他界面语言没有变化"。
|
|
|
|
|
|
## 问题分析
|
|
|
|
|
|
经过分析,发现问题的根本原因是:
|
|
|
|
|
|
1. **`SettingsView` 使用了错误的 `LanguageManager` 实例**:
|
|
|
- 使用了 `@StateObject private var languageManager = LanguageManager.shared`
|
|
|
- 这创建了一个新的 `LanguageManager` 实例,而不是观察共享的单例实例
|
|
|
|
|
|
2. **其他视图没有正确响应语言变化**:
|
|
|
- 使用 `.localized` 扩展的 `Text` 视图没有响应性
|
|
|
- 缺少强制UI刷新的机制
|
|
|
|
|
|
3. **缺少全局语言管理器访问**:
|
|
|
- 没有通过环境对象传递 `LanguageManager` 实例
|
|
|
|
|
|
## 修复方案
|
|
|
|
|
|
### 1. 修正 `LanguageManager` 实例使用
|
|
|
|
|
|
**修改前**:
|
|
|
```swift
|
|
|
// SettingsView.swift
|
|
|
@StateObject private var languageManager = LanguageManager.shared
|
|
|
```
|
|
|
|
|
|
**修改后**:
|
|
|
```swift
|
|
|
// SettingsView.swift
|
|
|
@EnvironmentObject private var languageManager: LanguageManager
|
|
|
```
|
|
|
|
|
|
### 2. 实现全局环境对象传递
|
|
|
|
|
|
**在 `MyQrCodeApp.swift` 中**:
|
|
|
```swift
|
|
|
@main
|
|
|
struct MyQrCodeApp: App {
|
|
|
@StateObject private var coreDataManager = CoreDataManager.shared
|
|
|
@StateObject private var languageManager = LanguageManager.shared // 新增
|
|
|
|
|
|
var body: some Scene {
|
|
|
WindowGroup {
|
|
|
ContentView()
|
|
|
.environmentObject(coreDataManager)
|
|
|
.environmentObject(languageManager) // 新增
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 3. 添加响应式刷新机制
|
|
|
|
|
|
**在 `LanguageManager.swift` 中**:
|
|
|
```swift
|
|
|
class LanguageManager: ObservableObject {
|
|
|
static let shared = LanguageManager()
|
|
|
|
|
|
@Published var currentLanguage: Language = .english
|
|
|
@Published var refreshTrigger = UUID() // 新增:用于强制刷新UI
|
|
|
|
|
|
// 切换语言
|
|
|
func switchLanguage(to language: Language) {
|
|
|
currentLanguage = language
|
|
|
UserDefaults.standard.set(language.rawValue, forKey: languageKey)
|
|
|
|
|
|
// 强制刷新所有UI
|
|
|
refreshTrigger = UUID() // 新增
|
|
|
|
|
|
// 通知语言变化
|
|
|
NotificationCenter.default.post(name: .languageChanged, object: language)
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 4. 为所有视图添加环境对象和刷新修饰符
|
|
|
|
|
|
为以下视图添加了 `@EnvironmentObject var languageManager: LanguageManager`:
|
|
|
|
|
|
- `ContentView.swift`
|
|
|
- `SettingsView.swift`
|
|
|
- `LanguageSettingsView.swift`
|
|
|
- `ScannerView.swift`
|
|
|
- `CameraPermissionView.swift`
|
|
|
- `ScanningOverlayView.swift`
|
|
|
- `TestAutoSelectButton.swift`
|
|
|
- `ScanningLineView.swift`
|
|
|
- `HistoryView.swift`
|
|
|
- `QRCodeStyleView.swift`
|
|
|
|
|
|
### 5. 为所有本地化文本添加刷新修饰符
|
|
|
|
|
|
为所有使用 `.localized` 的 `Text` 视图添加了 `.id(languageManager.refreshTrigger)` 修饰符:
|
|
|
|
|
|
```swift
|
|
|
Text("settings".localized)
|
|
|
.font(.system(size: 28, weight: .bold, design: .rounded))
|
|
|
.foregroundColor(.primary)
|
|
|
.id(languageManager.refreshTrigger) // 新增
|
|
|
```
|
|
|
|
|
|
### 6. 确保语言切换被正确调用
|
|
|
|
|
|
**在 `SettingsView.swift` 中**:
|
|
|
```swift
|
|
|
Picker("语言", selection: $languageManager.currentLanguage) {
|
|
|
ForEach(Language.allCases, id: \.self) { language in
|
|
|
Text(language.displayName).tag(language)
|
|
|
}
|
|
|
}
|
|
|
.pickerStyle(SegmentedPickerStyle())
|
|
|
.onChange(of: languageManager.currentLanguage) { newLanguage in // 新增
|
|
|
languageManager.switchLanguage(to: newLanguage)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
## 修复的文件列表
|
|
|
|
|
|
### 核心文件
|
|
|
- `MyQrCodeApp.swift` - 添加全局环境对象
|
|
|
- `LanguageManager.swift` - 添加刷新机制
|
|
|
- `SettingsView.swift` - 修正实例使用和添加刷新修饰符
|
|
|
|
|
|
### 视图文件
|
|
|
- `ContentView.swift`
|
|
|
- `LanguageSettingsView.swift`
|
|
|
- `ScannerView.swift`
|
|
|
- `CameraPermissionView.swift`
|
|
|
- `ScanningOverlayView.swift`
|
|
|
- `TestAutoSelectButton.swift`
|
|
|
- `ScanningLineView.swift`
|
|
|
- `HistoryView.swift`
|
|
|
- `QRCodeStyleView.swift`
|
|
|
|
|
|
## 技术原理
|
|
|
|
|
|
### 1. 环境对象传递
|
|
|
使用 `@EnvironmentObject` 确保所有视图都能访问同一个 `LanguageManager` 实例。
|
|
|
|
|
|
### 2. UUID 刷新机制
|
|
|
通过 `refreshTrigger` 属性生成新的 UUID,配合 `.id()` 修饰符强制 SwiftUI 重新渲染视图。
|
|
|
|
|
|
### 3. 响应式更新
|
|
|
当语言切换时,所有使用 `.id(languageManager.refreshTrigger)` 的视图都会重新渲染,确保显示新的语言文本。
|
|
|
|
|
|
## 测试结果
|
|
|
|
|
|
✅ **编译成功**:项目编译无错误
|
|
|
✅ **语言切换**:所有界面的文本都能正确响应语言变化
|
|
|
✅ **即时生效**:语言切换后立即生效,无需重启应用
|
|
|
✅ **持久化**:语言选择正确保存到 UserDefaults
|
|
|
|
|
|
## 总结
|
|
|
|
|
|
通过这次修复,我们解决了语言切换的核心问题:
|
|
|
|
|
|
1. **统一了 `LanguageManager` 实例的使用**
|
|
|
2. **实现了全局响应式语言切换**
|
|
|
3. **确保了所有UI元素都能正确更新**
|
|
|
|
|
|
现在用户可以在设置中切换语言,所有界面的文本都会立即更新为选择的语言,完全解决了之前报告的问题。
|