迅速改变语言

现在我知道苹果不推荐这个。

通常,您不应该在应用程序中更改iOS系统语言(通过使用AppleLanguages首选项)。 这违背了在“设置”应用程序中切换语言的基本iOS用户模型,并且还使用了未logging的首选项,这意味着在将来的某个时刻,关键名称可能会更改,这会破坏您的应用程序。

但是,这是一个应用程序,即时改变语言是合理的,只要相信我就可以了。 我也知道这个问题在这里被问到: 在运行iOS中,以编程方式更改语言 。 然而,这是越来越老,我想知道是否有任何更新,更好或更简单的方法来做到这一点。 目前在我的应用程序中,我有一个语言select屏幕。 点击该视图中的button,使用与该button关联的语言来调用以下function:

func changeLang(language: String) { if language != (currentLang as! String?)! { func handleCancel(alertView: UIAlertAction!) { } var alert = UIAlertController(title: NSLocalizedString("language", comment: "Language"), message: NSLocalizedString("languageWarning", comment: "Warn User of Language Change Different Than Defaults"), preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler:handleCancel)) alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default, handler:{ (UIAlertAction) in NSUserDefaults.standardUserDefaults().setObject([language], forKey: "AppleLanguages") NSUserDefaults.standardUserDefaults().synchronize() println(self.currentLang) let alert = UIAlertView() alert.title = NSLocalizedString("language", comment: "Sign In Failed") alert.message = NSLocalizedString("languageChangeNotification", comment: "Notify of language change") alert.addButtonWithTitle(NSLocalizedString("ok", comment: "Okay")) alert.show() self.performSegueWithIdentifier("welcome", sender: AnyObject?()) })) self.presentViewController(alert, animated: true, completion: { }) } else { self.performSegueWithIdentifier("welcome", sender: AnyObject?()) } } 

例:

 @IBAction func english(sender: UIButton) { changeLang("en") } 

如果用户select不同于他们自己的语言,他们会得到一个确认提醒,然后请求重新启动设备。 这是我想改变的。 看起来这个NSUSerDefaults部分在应用程序重新启动之前是不同步的。 证据:

 let currentLang: AnyObject? = NSLocale.preferredLanguages()[0] println(currentLang) // Prints english changeLang("zh-Hans") println(currentLang) // Prints english still until restart 

目前的苹果国际化系统非常棒,我打算使用它。 但是,如何通过强制更新NSUSerDefaults来dynamic更改语言?

编辑:我build议使用这个库来做到这一点。 祝你好运!

基本上你必须教你捆绑如何通过加载不同的包文件来切换语言。

我将我的Objective-C代码翻译成了Swift,并且保持NSBundle类别不变。

在这里输入图像说明

结果是一个视图控制器类,它提供了一个用于重写的languageDidChange()方法。


一个NSBundle + Language.h

 #import <Foundation/Foundation.h> @interface NSBundle (Language) +(void)setLanguage:(NSString*)language; @end 

一个NSBundle + Language.m

 #import "NSBundle+Language.h" #import <objc/runtime.h> static const char associatedLanguageBundle=0; @interface PrivateBundle : NSBundle @end @implementation PrivateBundle -(NSString*)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName { NSBundle* bundle=objc_getAssociatedObject(self, &associatedLanguageBundle); return bundle ? [bundle localizedStringForKey:key value:value table:tableName] : [super localizedStringForKey:key value:value table:tableName]; } @end @implementation NSBundle (Language) +(void)setLanguage:(NSString*)language { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ object_setClass([NSBundle mainBundle],[PrivateBundle class]); }); objc_setAssociatedObject([NSBundle mainBundle], &associatedLanguageBundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end 

AppDelegate.swift

 import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { NSNotificationCenter.defaultCenter().addObserver(self, selector: "languageWillChange:", name: "LANGUAGE_WILL_CHANGE", object: nil) let targetLang = NSUserDefaults.standardUserDefaults().objectForKey("selectedLanguage") as? String NSBundle.setLanguage((targetLang != nil) ? targetLang : "en") return true } func languageWillChange(notification:NSNotification){ let targetLang = notification.object as! String NSUserDefaults.standardUserDefaults().setObject(targetLang, forKey: "selectedLanguage") NSBundle.setLanguage(targetLang) NSNotificationCenter.defaultCenter().postNotificationName("LANGUAGE_DID_CHANGE", object: targetLang) } } 

BaseViewController.swift

 import UIKit class BaseViewController: UIViewController { @IBOutlet weak var englishButton: UIButton! @IBOutlet weak var spanishButton: UIButton! deinit{ NSNotificationCenter.defaultCenter().removeObserver(self) } override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: "languageDidChangeNotification:", name: "LANGUAGE_DID_CHANGE", object: nil) languageDidChange() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func switchLanguage(sender: UIButton) { var localeString:String? switch sender { case englishButton: localeString = "en" case spanishButton: localeString = "es" default: localeString = nil } if localeString != nil { NSNotificationCenter.defaultCenter().postNotificationName("LANGUAGE_WILL_CHANGE", object: localeString) } } func languageDidChangeNotification(notification:NSNotification){ languageDidChange() } func languageDidChange(){ } } 

ViewController.swift

 import UIKit class ViewController: BaseViewController { @IBOutlet weak var helloLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() } override func languageDidChange() { super.languageDidChange() self.helloLabel.text = NSLocalizedString("Hello", comment: "") } } 

而不是使用BaseViewController的子类,您的viewcontrollers也可以发布“LANGUAGE_WILL_CHANGE”,并听取“LANGUAGE_DID_CHANGE”

我在这里推送了完整的项目: ImmediateLanguageSwitchSwift

对我来说,“ Swift Localize ”库解决了即时语言切换问题。