本文主要講述國際化過程中所遇到的那些問題悼瘾,國際化的詳細步驟可以參考:3分鐘實現(xiàn)iOS語言本地化/國際化(圖文詳解)
-
APP內(nèi)設(shè)置了語言君仆,切換后語言沒有生效
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:language, nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
沒有生效树叽,這是因為設(shè)置AppleLanguages字段的話土辩,只會在下次啟動App才會生效,在App啟動后就已經(jīng)生成了一個Bundle循诉,里面識別好了對應(yīng)著AppleLanguages的國際化文件,在App運行期間設(shè)置這個字段撇他,是不生效的茄猫,所以我們?nèi)バ薷倪@個Bundle,寫一個NSBundle的擴展逆粹,這里要用到runtime中的關(guān)聯(lián):
.h
#import <Foundation/Foundation.h>
@interface NSBundle (Language)
+ (void)setLanguage:(NSString *)language;
@end
.m
#import "NSBundle+Language.h"
#import <objc/runtime.h>
static const char _bundle = 0;
@interface BundleEx : NSBundle
@end
@implementation BundleEx
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName {
NSBundle *bundle = objc_getAssociatedObject(self, &_bundle);
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], [BundleEx class]);
});
/*
*objc_setAssociatedObject來把一個對象與另外一個對象進行關(guān)聯(lián)募疮。該函數(shù)需要四個參數(shù):源對象,關(guān)鍵字僻弹,關(guān)聯(lián)的對象和一個關(guān)聯(lián)策略阿浓。
*關(guān)鍵字是一個void類型的指針。每一個關(guān)聯(lián)的關(guān)鍵字必須是唯一的蹋绽。通常都是會采用靜態(tài)變量來作為關(guān)鍵字芭毙。
*/
objc_setAssociatedObject([NSBundle mainBundle], &_bundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
然后在選中語言的時候,重新設(shè)置根控制器
- (IBAction)clickEvent:(id)sender {
[self changeLanguageTo:@"zh-Hans"];
}
- (IBAction)selectBtnEvent:(id)sender {
[self changeLanguageTo:@"en"];
}
- (void)changeLanguageTo:(NSString *)language {
// 設(shè)置語言
[NSBundle setLanguage:language];
// 然后將設(shè)置好的語言存儲好卸耘,下次進來直接加載
[[NSUserDefaults standardUserDefaults] setObject:language forKey:@"myLanguage"];
[[NSUserDefaults standardUserDefaults] synchronize];
//重新設(shè)置根控制器
ViewController *VC = [[ViewController alloc] init];
[UIApplication sharedApplication].keyWindow.backgroundColor = [UIColor whiteColor];
[UIApplication sharedApplication].keyWindow.rootViewController = VC;
}
然后你會發(fā)現(xiàn):如果這個根控制器直接用storyboard或者XIB的話退敦,里面view會消失了。這是因為:重新設(shè)置了根控制器時蚣抗,會執(zhí)行
- (void)viewDidLoad {
[super viewDidLoad];
}
如果不是在這里初始化的控件侈百,是無法加載進來的。
-
如果使用
#define NSLocalizedString(key, comment) \ [NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil]
這個方法,加載的key中間有空格的話钝域,例如:I like
讽坏,即使點擊改變了語言,但是它還是保持原來語言的情況例证。
寫的比較亂路呜,可以參考demoiOS國際化