在做跨国项目的时候经常需要使用本地化的技术,但是在开发过程中往往需要提交给测试者一个测试人员能够看得懂的版本,通过runtime机制可以实现强制应用使用指定语言,具体代码如下:
var kBundleKey = "kBundleKey"
class ExBundle: Bundle {
override func localizedString(forKey key: String, value: String?, table tableName: String?) -> String {
let b = objc_getAssociatedObject(self, &kBundleKey) as? Bundle
if b == nil { return super.localizedString(forKey: key, value: value, table: tableName) }
return b!.localizedString(forKey: key, value: value, table: tableName)
}
}
首先创建一个ExBundle类继承自Bundle,重写方法localizedString,这个方法无论是加在localizable.strings文件还是使用xib或者storyboard文件的多语言时都会调用该方法,例如你调用NSLocalizedString最终应用会调用Bundle的localizedString去查找指定tableName下的key并返回值。再来看下面的代码:
// AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
object_setClass(Bundle.main, ExBundle.classForCoder())
let path = Bundle.main.path(forResource: "zh-Hans", ofType: "lproj")
let bundle = Bundle.init(path: path!)
objc_setAssociatedObject(Bundle.main, &kBundleKey, bundle, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return true
}
通过runtime机制,将Bundle.main对象的类型设置为ExBundle,并且通过objc_setAssociatedObject方法为Bundle.main对象设置一个为bundle属性,该bundle对象就是指向指定多语言的文件夹。
最后如果程序内有任何使用多语言的地方,都会根据kBundleKey取出bundle对象,通过bundle对象的localizedString来返回文言。
网友评论