内联函数替代有参宏

最近接到了一个老板的需求,要把咱们的程序进行国际化,就是新增一个英语的支持。
大体的需求是这个样子的:程序内添加语言切换选项,并在第一次安装的时候自动选择合适的语言(中文系统的手机(不管简体中文繁体中文)一概使用简体中文,其它语言的(不管英语仍是法语德语)都默认使用英文)。
其实若是只是添加多语言支持,再也不应用内切换语言,苹果的开发就能很好的支持了。就是多了这个应用内切换语言(像微信那样),逻辑就复杂了不少。
由于以前的时候字符串都是写死在程序中的,因此不可能大范围的更改。又要涉及到语言的切换,因此,只能用一个折中的方法,写个宏去处理。
实现的逻辑大约是这个样子的:userdefaults存一个用户设置的语言,若是没有存储就根据系统的语言去作逻辑判断,最终获得肯定使用哪一种语言而后再去读取相应的语言文件,根据key-value去查找,若是查找不到就默认的使用key做为value使用了。
逻辑大约应该是这样的:html

//OC
[[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@",([[[NSUserDefaults standardUserDefaults] objectForKey:@"Language"] hasPrefix:@"zh"] || ([[NSUserDefaults standardUserDefaults] objectForKey:@"Language"] == nil && [[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode] hasPrefix:@"zh"]))?@"zh-Hans":@"en"] ofType:@"lproj"]] localizedStringForKey:(key) value:key table:nil];

//swift
func L(key:String) -> String {
    var language:String? = NSUserDefaults .standardUserDefaults().objectForKey("Language") as? String
    if language == nil {
        language = NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode)! as? String
    }
    let bundle:NSBundle = NSBundle.init(path: NSBundle.mainBundle().pathForResource(((language!.hasPrefix("zh")) ? "zh-Hans" : "en"), ofType: "lproj")!)!
    return NSLocalizedString(key, tableName: nil, bundle: bundle, value: key, comment: key)
}

以上的key就是宏的形参了。swift

这样的宏实际上是在编译以前就进行了代码的替换,其实就是把工程的全部的相关的地方替换上了这么长的代码,而后再进行编译(swift的实际上是用一个public的函数去处理的,不是代码替换)。微信

后来发现有个更好的东西能够替换这个,就是内联函数函数

内联函数首先是一个函数,能够有函数的参数检查的优点spa

有普通的函数不具有的优点,函数的代码本质是放在符号表中的,使用的时候进行替换,没有了普通函数调用的时候的开销.net

执行效率和宏定义本质是同样的(内联函数是编译器首先在函数调用处使用函数体自己语句替换了函数调用语句,而后编译替换后的代码),可是还有优点code

更多的内联函数的定义仍是放几个博客吧:orm

http://blog.csdn.net/sqc3375177/article/details/8264778htm

http://blog.csdn.net/chsadin/article/details/47982923blog

http://www.cnblogs.com/QG-whz/p/4641479.html

 

OC的差很少这个样子写法:

static inline NSString * L (NSString * key) {
    return [[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@",([[[NSUserDefaults standardUserDefaults] objectForKey:@"Language"] hasPrefix:@"zh"] || ([[NSUserDefaults standardUserDefaults] objectForKey:@"Language"] == nil && [[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode] hasPrefix:@"zh"]))?@"zh-Hans":@"en"] ofType:@"lproj"]] localizedStringForKey:(key) value:key table:nil];
}


swift的这样就能够了

@inline(__always) func L(key:String) -> String {
    var language:String? = NSUserDefaults .standardUserDefaults().objectForKey("Language") as? String
    if language == nil {
        language = NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode)! as? String
    }
    let bundle:NSBundle = NSBundle.init(path: NSBundle.mainBundle().pathForResource(((language!.hasPrefix("zh")) ? "zh-Hans" : "en"), ofType: "lproj")!)!
    return NSLocalizedString(key, tableName: nil, bundle: bundle, value: key, comment: key)
}
@inline后面的括号里面能够有两种关键词“never”和“__always”naver是能够避免这个替代的时候使用了过大的代码块。这个到底使用普通函数仍是内联函数是由编译器决定的(若是内联函数里面有循环和开关语句)就直接和普通函数没什么区别了__always其实就是程序的运行效率优先了,无论什么,直接按照内联函数对待了总结一下,就是之后写有参宏的时候直接用内联函数就行了,写代码有提示还能尽量的保证不出错。
相关文章
相关标签/搜索