iOS开发之APP内部切换语言

作者: 季末微夏 | 来源:发表于2018-11-26 23:56 被阅读387次

    前言

    iOS开发中,随着APP越来越完善,很多APP都做了国际化,也实现了APP内部切换语言。

    原理

    国际化都会走到NSBundle的- (NSString *)localizedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName方法,使用自定义Bundle替换NSBundle,通过切换根控制器来完成APP内部切换语言。

    1.拦截国际化方法

    通过分类和runtime来实现拦截,将Bundle替换为自定义CLBundle。

    + (void)load {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            //动态继承、交换,方法类似KVO,通过修改[NSBundle mainBundle]对象的isa指针,使其指向它的子类CLBundle,这样便可以调用子类的方法;其实这里也可以使用method_swizzling来交换mainBundle的实现,来动态判断,可以同样实现。
            object_setClass([NSBundle mainBundle], [CLBundle class]);
        });
    }
    

    2.重写方法判断加载哪一种语言

    重写mainBundle方法,通过语言管理类获取当前应该加载哪一种语言。

    - (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName {
        if ([CLBundle cl_mainBundle]) {
            return [[CLBundle cl_mainBundle] localizedStringForKey:key value:value table:tableName];
        } else {
            return [super localizedStringForKey:key value:value table:tableName];
        }
    }
    
    + (NSBundle *)cl_mainBundle {
        if ([NSBundle currentLanguage].length) {
            NSString *path = [[NSBundle mainBundle] pathForResource:[NSBundle currentLanguage] ofType:@"lproj"];
            if (path.length) {
                return [NSBundle bundleWithPath:path];
            }
        }
        return nil;
    }
    
    + (NSString *)currentLanguage {
        return [CLLanguageManager userLanguage] ? : [NSLocale preferredLanguages].firstObject;
    }
    

    3.语言管理类

    将语言切换调用设置简单封装,方便调用。

    + (void)setUserLanguage:(NSString *)userLanguage {
        //跟随手机系统
        if (!userLanguage.length) {
            [self resetSystemLanguage];
            return;
        }
        //用户自定义
        [[NSUserDefaults standardUserDefaults] setValue:userLanguage forKey:CLUserLanguageKey];
        [[NSUserDefaults standardUserDefaults] setValue:@[userLanguage] forKey:@"AppleLanguages"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    + (NSString *)userLanguage {
        return [[NSUserDefaults standardUserDefaults] valueForKey:CLUserLanguageKey];
    }
    
    /**
     重置系统语言
     */
    + (void)resetSystemLanguage {
        [[NSUserDefaults standardUserDefaults] removeObjectForKey:CLUserLanguageKey];
        [[NSUserDefaults standardUserDefaults] setValue:nil forKey:@"AppleLanguages"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    

    4.切换根控制器来切换语言

    为了减少工作量,直接切换根控制器来达到语言切换。

    [CLLanguageManager setUserLanguage:@"en"];
     CLTabbarController *tabbarController = [[CLTabbarController alloc] init];
    tabbarController.selectedIndex = 3;
    UINavigationController *navigationController = tabbarController.selectedViewController;
    NSMutableArray *viewControllers = navigationController.viewControllers.mutableCopy;
        //取出我的页面,提前加载,解决返回按钮不变化
     CLMyController *me = (CLMyController *)[viewControllers firstObject];
    [me loadViewIfNeeded];
        //新建设置语言页面
    CLChangeLanguageController *languageController = [[CLChangeLanguageController alloc] init];
    languageController.hidesBottomBarWhenPushed = YES;
    [viewControllers addObject:languageController];
        //解决奇怪的动画bug。
    dispatch_async(dispatch_get_main_queue(), ^{
        [UIApplication sharedApplication].keyWindow.rootViewController = tabbarController;
        navigationController.viewControllers = viewControllers;
        CLLog(@"已切换到语言 %@", [NSBundle currentLanguage]);
    });
    

    效果图

    1.gif

    总结

    以上是使用国际化来实现APP内部切换语言,希望能够给大家帮助,demo地址--->>CLDemo

    相关文章

      网友评论

        本文标题:iOS开发之APP内部切换语言

        本文链接:https://www.haomeiwen.com/subject/mkxwqqtx.html