本文记录iOS 多语言全局适配解决方案,适用于项目中后期快速适配多语言;
实现思路:runtime method swizzling,拦截UILabel 的setText:
方法、UIViewController 的 setTitle:
方法、UINavigationItem 的setTitle:
方法;
一、多语言基本适配:
该部分请参考:VV木公子
作品:
3分钟实现iOS语言本地化/国际化(图文详解)!
二、多语言配置读取:
NSString *GlobalLanguePath;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self configAppLangue];
}
-(void)configAppLangue{
//根据NSUserDefaults的key去取多语言类型, k_AppLaguageKey为与用户相关的 Key
NSString *laguageType = [[NSUserDefaults standardUserDefaults] objectForKey:k_AppLaguageKey];
if (laguageType == nil) { // 如果没有用户偏好则根据系统第一语言配置启动,并且不做偏好设置记录
NSString *preferredLanguage = [NSLocale preferredLanguages][0];
if ([preferredLanguage hasPrefix:@"en"]) {
laguageType = @"en";
}else{
laguageType = @"zh-Hans";
}
}
NSLog(@"当前语言环境:%@",laguageType);
GlobalLanguePath = [[NSBundle mainBundle] pathForResource:laguageType ofType:@"lproj"];
}
为了方便使用,pch 来个宏定义:
// 语言加载路径 全局变量
extern NSString *GlobalLanguePath;
#define k_LangueKey(key) [[NSBundle bundleWithPath:GlobalLanguePath] localizedStringForKey:key value:nil table:@"Localizable"]
使用如下:
UILabel *label = [UILabel new];
label.text = k_LangueKey(@"你所配置的key");
一点注意: 如若手动切换语言环境,而不是跟随系统语言环境变化,则在语言切换之后重新初始化 window.rootViewController ,然后代码 push 到切换语言之前的 controller(如XXSettingViewController) 即可;
三、全局修改方式:
到此处可以使用 k_LangueKey() 一处一处修改了,然后在项目后期何其麻烦又是何其繁琐,所以自然想到拦截 UILabel 的 setText 方法:
#import "NSObject+swapMethod.h"
#import <UIKit/UIKit.h>
@implementation UILabel (Langues)
+(void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swapSelector:@selector(setText:) toSelector:@selector(langues_setText:)];
});
}
-(void)langues_setText:(NSString *)text{
[self langues_setText:k_LangueKey(text)];
}
@end
然而,此时也许你会发现 导航栏 title 和 tabbarItem title 全变黑了,So ...
#import "NSObject+swapMethod.h"
@implementation UINavigationItem (Langues)
+(void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swapSelector:@selector(setTitle:) toSelector:@selector(langues_setTitle:)];
});
}
-(void)langues_setTitle:(NSString *)title{
[self langues_setTitle:k_LangueKey(title)];
}
@end
#import "NSObject+swapMethod.h"
@implementation UIViewController (Langues)
+(void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swapSelector:@selector(setTitle:) toSelector:@selector(langues_setTitle:)];
});
}
-(void)langues_setTitle:(NSString *)title{
[self langues_setTitle:k_LangueKey(title)];
}
@end
最后附上 swapSelector:toSelector方法:
#import "NSObject+swapMethod.h"
#import <objc/runtime.h>
@implementation NSObject (swapMethod)
+(void)swapSelector:(SEL)systemSelector toSelector:(SEL)customSelector{
SEL org_Selector = systemSelector;
SEL new_Selector = customSelector;
Method org_method = class_getInstanceMethod([self class], org_Selector);
Method new_method = class_getInstanceMethod([self class], new_Selector);
BOOL isAdd = class_addMethod(self, org_Selector, method_getImplementation(new_method), method_getTypeEncoding(new_method));
if (isAdd) {
class_replaceMethod(self, customSelector, method_getImplementation(new_method), method_getTypeEncoding(new_method));
}else{
method_exchangeImplementations(org_method, new_method);
}
}
@end
网友评论