Swift实现无需重启App点击按钮切换应用语言问题咨询
Hey there! 看你正在搞iOS应用内一键切换语言还不用重启的功能,我帮你把代码补全优化,再唠唠关键要点,保证管用:
完整实现方案
首先咱们把L102Language工具类补全,它负责处理语言的存储、获取和本地化字符串的加载:
let APPLE_LANGUAGE_KEY = "AppleLanguages" class L102Language { // 获取当前生效的语言 class func currentAppleLanguage() -> String { let userDefaults = UserDefaults.standard let storedLanguages = userDefaults.object(forKey: APPLE_LANGUAGE_KEY) as? [String] ?? [] return storedLanguages.first ?? "en" } // 设置目标语言并持久化 class func setAppleLanguageTo(lang: String) { let userDefaults = UserDefaults.standard userDefaults.set([lang], forKey: APPLE_LANGUAGE_KEY) userDefaults.synchronize() // 兼容iOS 10以下版本,新版本可以省略,但加上不影响 } // 便捷获取本地化字符串(解决系统缓存不更新的问题) class func localizedString(for key: String) -> String { guard let langBundlePath = Bundle.main.path(forResource: currentAppleLanguage(), ofType: "lproj") else { return NSLocalizedString(key, comment: "") } let targetBundle = Bundle(path: langBundlePath) ?? Bundle.main return NSLocalizedString(key, tableName: nil, bundle: targetBundle, value: "", comment: "") } }
然后修正你的按钮点击事件代码(注意你之前拼写错了setAppleLAnguageTo,少了个n),还要加上界面刷新的逻辑:
@IBAction func convertlang(_ sender: Any) { let currentLang = L102Language.currentAppleLanguage() if currentLang == "en" { L102Language.setAppleLanguageTo(lang: "ar") UIView.appearance().semanticContentAttribute = .forceRightToLeft } else { L102Language.setAppleLanguageTo(lang: "en") UIView.appearance().semanticContentAttribute = .forceLeftToRight } // 发送通知,让所有界面知道语言变了,赶紧刷新 NotificationCenter.default.post(name: NSNotification.Name("LanguageChanged"), object: nil) // 额外:如果当前页面需要立即刷新布局,也可以手动触发 self.view.setNeedsLayout() }
最后,每个需要本地化的ViewController都要监听这个通知,刷新控件文字:
override func viewDidLoad() { super.viewDidLoad() // 监听语言切换通知 NotificationCenter.default.addObserver(self, selector: #selector(refreshLocalizedUI), name: NSNotification.Name("LanguageChanged"), object: nil) // 初始化时就加载正确的本地化文字 refreshLocalizedUI() } @objc private func refreshLocalizedUI() { // 把所有需要本地化的控件都重新设置一遍文字 self.title = L102Language.localizedString(for: "app_title") self.welcomeLabel.text = L102Language.localizedString(for: "welcome_message") self.convertButton.setTitle(L102Language.localizedString(for: "switch_lang_btn"), for: .normal) // 其他控件同理... } deinit { // 记得移除通知监听,避免内存泄漏 NotificationCenter.default.removeObserver(self) }
关键注意点
- 语义布局适配:
UIView.appearance().semanticContentAttribute会影响后续创建的视图,但已经存在的视图可能需要手动设置这个属性,或者通过view.setNeedsLayout()触发重新布局。 - 字符串缓存问题:系统自带的
NSLocalizedString会缓存Bundle信息,所以咱们自定义了localizedString方法,直接从对应语言的lproj包取字符串,保证切换后立即生效。 - 界面刷新必须做:已经创建的控件不会自动更新文字,所以一定要通过通知或者其他方式触发所有界面重新加载本地化内容。
内容的提问来源于stack exchange,提问作者Lama




