iOS Crazies

iOS 多语言全局适配

2018-09-06  本文已影响20人  hehtao

本文记录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

So End All

上一篇下一篇

猜你喜欢

热点阅读