本文主要讲述国际化过程中所遇到的那些问题,国际化的详细步骤可以参考:3分钟实现iOS语言本地化/国际化(图文详解)
-
APP内设置了语言,切换后语言没有生效
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:language, nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
没有生效,这是因为设置AppleLanguages字段的话,只会在下次启动App才会生效,在App启动后就已经生成了一个Bundle,里面识别好了对应着AppleLanguages的国际化文件,在App运行期间设置这个字段,是不生效的,所以我们去修改这个Bundle,写一个NSBundle的扩展,这里要用到runtime中的关联:
.h
#import
@interface NSBundle (Language)
+ (void)setLanguage:(NSString *)language;
@end
.m
#import "NSBundle+Language.h"
#import
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来把一个对象与另外一个对象进行关联。该函数需要四个参数:源对象,关键字,关联的对象和一个关联策略。
*关键字是一个void类型的指针。每一个关联的关键字必须是唯一的。通常都是会采用静态变量来作为关键字。
*/
objc_setAssociatedObject([NSBundle mainBundle], &_bundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
然后在选中语言的时候,重新设置根控制器
- (IBAction)clickEvent:(id)sender {
[self changeLanguageTo:@"zh-Hans"];
}
- (IBAction)selectBtnEvent:(id)sender {
[self changeLanguageTo:@"en"];
}
- (void)changeLanguageTo:(NSString *)language {
// 设置语言
[NSBundle setLanguage:language];
// 然后将设置好的语言存储好,下次进来直接加载
[[NSUserDefaults standardUserDefaults] setObject:language forKey:@"myLanguage"];
[[NSUserDefaults standardUserDefaults] synchronize];
//重新设置根控制器
ViewController *VC = [[ViewController alloc] init];
[UIApplication sharedApplication].keyWindow.backgroundColor = [UIColor whiteColor];
[UIApplication sharedApplication].keyWindow.rootViewController = VC;
}
然后你会发现:如果这个根控制器直接用storyboard或者XIB的话,里面view会消失了。这是因为:重新设置了根控制器时,会执行
- (void)viewDidLoad {
[super viewDidLoad];
}
如果不是在这里初始化的控件,是无法加载进来的。
-
如果使用
#define NSLocalizedString(key, comment) \ [NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil]
这个方法,加载的key中间有空格的话,例如:I like
,即使点击改变了语言,但是它还是保持原来语言的情况。
写的比较乱,可以参考demoiOS国际化