iOS对第三方框架的国际化改为跟随系统改变

前言

当一个项目要求在应用内切换应用语言,对于我们自己编写的代码,当然可以统一处理。比较麻烦的是,要求第三方框架的语言也随之变化。应用内切换语言的实现方法,可以参考上篇文章。

分析

为了实现需求,我们有以下两种做法

  • 直接修改源码
  • 运行时机制之交换方法
    若采取第一种方法,将不利于我们使用pod来管理第三方框架。所以在这里我们使用运行时,交换方法(这里也可以参考我的另一篇文章,交换方法)。

例子

一、分析

这里拿MJRefresh做例子,该框架语言默认是跟随系统语言变化的。这里我需要改为跟随应用内选择的语言。

这里MJRefresh框架中NSBundle+MJRefresh的一个分类方法

+ (NSString *)mj_localizedStringForKey:(NSString *)key value:(NSString *)value
{
    static NSBundle *bundle = nil;
    if (bundle == nil) {
        // (iOS获取的语言字符串比较不稳定)目前框架只处理en、zh-Hans、zh-Hant三种情况,其他按照系统默认处理
        NSString *language = [NSLocale preferredLanguages].firstObject;
        if ([language hasPrefix:@"en"]) {
            language = @"en";
        } else if ([language hasPrefix:@"zh"]) {
            if ([language rangeOfString:@"Hans"].location != NSNotFound) {
                language = @"zh-Hans"; // 简体中文
            } else { // zh-Hant\zh-HK\zh-TW
                language = @"zh-Hant"; // 繁體中文
            }
        } else {
            language = @"en";
        }

        // 从MJRefresh.bundle中查找资源
        bundle = [NSBundle bundleWithPath:[[NSBundle mj_refreshBundle] pathForResource:language ofType:@"lproj"]];
    }
    value = [bundle localizedStringForKey:key value:value table:nil];
    return [[NSBundle mainBundle] localizedStringForKey:key value:value table:nil];
}

可以看出,只要交换这个方法,使之执行我们的方法,即可实现我们的需求。

二、实现

在自己的国际化管理者类中,实现以下代码,这里是我实现的

+ (void)load
{
    // 交换MJ的国际化方法
    Method mjMethod = class_getClassMethod([NSBundle class],@selector(mj_localizedStringForKey:value:));
    Method myMethod = class_getClassMethod(self, @selector(hook_mj_localizedStringForKey:value:));
    method_exchangeImplementations(mjMethod, myMethod);
}

/// hook刷新控件的提示文字
+ (NSString *)hook_mj_localizedStringForKey:(NSString *)key value:(NSString *)value
{
    NSString *language =  [LocalizationManager languageFormat:[LocalizationManager userLanguage]];
    NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mj_refreshBundle] pathForResource:language ofType:@"lproj"]];
    return [bundle localizedStringForKey:key value:nil table:@"Localizable"];
}

其实整个思路是很简单的,就是在不动源码的前提下,实现自己想实现的方法。

注意

class_getClassMethod和class_getInstanceMethod区别

  • class_getClassMethod
    • 获得类方法
  • class_getInstanceMethod
    • 获得对象方法

一开始在这里踩坑了,在这里记录一下 ,大家使用的时候注意下就好了

你可能感兴趣的:(iOS)