You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MyQRCode/docs/LANGUAGE_SWITCHING_BUG_FIX_...

4.8 KiB

语言切换Bug修复报告

问题描述

用户报告了一个语言切换的bug"设置语言有bug语言更改后其他界面语言没有变化"。

问题分析

经过分析,发现问题的根本原因是:

  1. SettingsView 使用了错误的 LanguageManager 实例

    • 使用了 @StateObject private var languageManager = LanguageManager.shared
    • 这创建了一个新的 LanguageManager 实例,而不是观察共享的单例实例
  2. 其他视图没有正确响应语言变化

    • 使用 .localized 扩展的 Text 视图没有响应性
    • 缺少强制UI刷新的机制
  3. 缺少全局语言管理器访问

    • 没有通过环境对象传递 LanguageManager 实例

修复方案

1. 修正 LanguageManager 实例使用

修改前

// SettingsView.swift
@StateObject private var languageManager = LanguageManager.shared

修改后

// SettingsView.swift
@EnvironmentObject private var languageManager: LanguageManager

2. 实现全局环境对象传递

MyQrCodeApp.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

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. 为所有本地化文本添加刷新修饰符

为所有使用 .localizedText 视图添加了 .id(languageManager.refreshTrigger) 修饰符:

Text("settings".localized)
    .font(.system(size: 28, weight: .bold, design: .rounded))
    .foregroundColor(.primary)
    .id(languageManager.refreshTrigger) // 新增

6. 确保语言切换被正确调用

SettingsView.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元素都能正确更新

现在用户可以在设置中切换语言,所有界面的文本都会立即更新为选择的语言,完全解决了之前报告的问题。