冬宝不乖不听话 發表於 2020-12-15 21:36:00

iOS开发之APP内部切换语言

<h2>前言</h2>
<p>iOS开发中,随着APP越来越完善,很多APP都做了国际化,也实现了APP内部切换语言。</p>
<p><strong>作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS交流群:812157648,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!</strong></p>
<h2>原理</h2>
<p>国际化都会走到NSBundle的- (NSString *)localizedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName方法,使用自定义Bundle替换NSBundle,通过切换根控制器来完成APP内部切换语言。</p>
<h4>1.拦截国际化方法</h4>
<p>通过分类和runtime来实现拦截,将Bundle替换为自定义CLBundle。</p>
<div class="cnblogs_code">
<pre>+ (<span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)">)load {
    </span><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> dispatch_once_t onceToken;
    dispatch_once(</span>&amp;onceToken, ^<span style="color: rgba(0, 0, 0, 1)">{
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">动态继承、交换,方法类似KVO,通过修改对象的isa指针,使其指向它的子类CLBundle,这样便可以调用子类的方法;其实这里也可以使用method_swizzling来交换mainBundle的实现,来动态判断,可以同样实现。</span>
      object_setClass(, );
    });
}</span></pre>
</div>
<h4>2.重写方法判断加载哪一种语言</h4>
<p>重写mainBundle方法,通过语言管理类获取当前应该加载哪一种语言。</p>
<div class="cnblogs_code">
<pre>- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *<span style="color: rgba(0, 0, 0, 1)">)tableName {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> () {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> [ localizedStringForKey:key value:value table:tableName];
    } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ;
    }
}

</span>+ (NSBundle *<span style="color: rgba(0, 0, 0, 1)">)cl_mainBundle {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (.length) {
      NSString </span>*path = [ pathForResource: ofType:<span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">lproj</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">];
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (path.length) {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ;
      }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> nil;
}

</span>+ (NSString *<span style="color: rgba(0, 0, 0, 1)">)currentLanguage {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> ?<span style="color: rgba(0, 0, 0, 1)"> : .firstObject;
}</span></pre>
</div>
<h4>3.语言管理类</h4>
<p>将语言切换调用设置简单封装,方便调用。</p>
<div class="cnblogs_code">
<pre>+ (<span style="color: rgba(0, 0, 255, 1)">void</span>)setUserLanguage:(NSString *<span style="color: rgba(0, 0, 0, 1)">)userLanguage {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">跟随手机系统</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">userLanguage.length) {
      ;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">用户自定义</span>
<span style="color: rgba(0, 0, 0, 1)">    [ setValue:userLanguage forKey:CLUserLanguageKey];
    [ setValue:@ forKey:</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">AppleLanguages</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">];
    [ synchronize];
}

</span>+ (NSString *<span style="color: rgba(0, 0, 0, 1)">)userLanguage {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> [ valueForKey:CLUserLanguageKey];
}

</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
重置系统语言
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
+ (<span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)">)resetSystemLanguage {
    [ removeObjectForKey:CLUserLanguageKey];
    [ setValue:nil forKey:</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">AppleLanguages</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">];
    [ synchronize];
}</span></pre>
</div>
<h4>4.切换根控制器来切换语言</h4>
<p>为了减少工作量,直接切换根控制器来达到语言切换。</p>
<div class="cnblogs_code">
<pre>;
CLTabbarController </span>*tabbarController =<span style="color: rgba(0, 0, 0, 1)"> [ init];
tabbarController.selectedIndex </span>= <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">;
UINavigationController </span>*navigationController =<span style="color: rgba(0, 0, 0, 1)"> tabbarController.selectedViewController;
NSMutableArray </span>*viewControllers =<span style="color: rgba(0, 0, 0, 1)"> navigationController.viewControllers.mutableCopy;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">取出我的页面,提前加载,解决返回按钮不变化</span>
CLMyController *me = (CLMyController *<span style="color: rgba(0, 0, 0, 1)">);
;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">新建设置语言页面</span>
CLChangeLanguageController *languageController =<span style="color: rgba(0, 0, 0, 1)"> [ init];
languageController.hidesBottomBarWhenPushed </span>=<span style="color: rgba(0, 0, 0, 1)"> YES;
;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">解决奇怪的动画bug。</span>
dispatch_async(dispatch_get_main_queue(), ^<span style="color: rgba(0, 0, 0, 1)">{
    .keyWindow.rootViewController </span>=<span style="color: rgba(0, 0, 0, 1)"> tabbarController;
    navigationController.viewControllers </span>=<span style="color: rgba(0, 0, 0, 1)"> viewControllers;
    CLLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">已切换到语言 %@</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, );
});</span></pre>
</div>
<h2>效果图</h2>
<p><img src="https://img2020.cnblogs.com/blog/2240560/202012/2240560-20201215213454910-678390137.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>总结</h2>
<p>以上是使用国际化来实现APP内部切换语言,希望能够给大家帮助,demo地址—&gt;&gt;CLDemo</p>
<p>原文作者:季末微夏<br>原文地址:https://www.jianshu.com/p/5ee17137746b</p><br><br>
来源:https://www.cnblogs.com/fadaijun/p/14141182.html
頁: [1]
查看完整版本: iOS开发之APP内部切换语言