runtime在應(yīng)用國際化上的實(shí)踐

前言

在應(yīng)用開發(fā)時腻惠,某一天我們的產(chǎn)品經(jīng)理興高采烈的和我們說:“我們的產(chǎn)品即將走向國際化,我們要做美國糜芳,英國飒货,德國...進(jìn)行推廣∏涂ⅲ” 這意味著我們需要做國際化版本了塘辅。

怎么會這樣。皆撩。

我們的代碼經(jīng)常會有下面這樣的代碼

 cell.textLabel.text = @"我的文本";

或者是在直接在 xib扣墩、StoryBoard 直接設(shè)置屬性了。

國際化

在iOS開發(fā)扛吞,我們是如何實(shí)現(xiàn)國際化的呢呻惕?對這一塊不了解的同學(xué)可以看這篇文章

雖然 Xib滥比、StoryBoard 都可以設(shè)置國際化亚脆。但我們
還是習(xí)慣全部寫在一個 strings 中,這樣方便做翻譯的同學(xué)進(jìn)行翻譯盲泛。

那這樣我們要進(jìn)行國際化的流程是

這樣實(shí)在太煩了濒持。。這么多控件寺滚。柑营。

使用runtime解決問題

setText 國際化

國際化主要的工作就是在 setText 之前需要調(diào)用 NSLocalizedString 生成國際化后的字符串。

目前代碼使我們糾結(jié)的地方是我們就直接使用 setText 了村视。我們希望在setText時插入一段國際化的代碼官套。

我們希望在執(zhí)行某個函數(shù)之前插入一段代碼,Runtime的 Method Swizzling 可以實(shí)現(xiàn)這樣的功能。

@implementation UILabel(NewLabel)


+ (void)load {
    [UILabel configSwizzled];
}

+ (void)configSwizzled {
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        // When swizzling a class method, use the following:
        // Class class = object_getClass((id)self);
        
        SEL originalSelector = @selector(setText:);
        SEL swizzledSelector = @selector(setNewText:);
        
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));
        
        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
    
}


- (void)setNewText:(NSString *)text {

    [self setNewText:NSLocalizedString(text, nil)];
}


@end

  • 我們使用分類擴(kuò)展 UILabel 奶赔。
  • 然后重寫 load 這個函數(shù)惋嚎,在里面進(jìn)行Swizzle的初始化。
  • 在這里我們把 setText Swizzle setNewText.
  • setNewText 中我們我們調(diào)用 NSLocalizedString 進(jìn)行國際化處理纺阔。

好了瘸彤,這樣我們解決了在代碼中 setText 的國際化問題。

Xib StoryBoard 國際化

這里我們發(fā)現(xiàn)笛钝,Xib StoryBoard 中設(shè)置屬性的控件不會調(diào)用 setText 质况。

那這我們怎么解決呢? 讓他們調(diào)用一下 setText 吧玻靡。那我們需要怎么做结榄? Xib StoryBoard 的控件,必然會走 initWithCoder 這個初始化函數(shù)囤捻。我們在再次使用 Runtime 的黑魔法臼朗,讓 initWithCoder 執(zhí)行完后,我們在調(diào)用一下 setText蝎土。

直接看代碼吧:


+ (void)configSwizzled {

...

dispatch_once(&onceToken2, ^{
        Class class = [self class];
        // When swizzling a class method, use the following:
        // Class class = object_getClass((id)self);
        
        SEL originalSelector = @selector(initWithCoder:);
        SEL swizzledSelector = @selector(initNewWithCoder:);
        
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));
        
        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });


}

- (instancetype)initNewWithCoder:(NSCoder *)aDecoder {
    
    id result = [self initNewWithCoder:aDecoder];
    
    [self setText:self.text];
    
    return result;
}

So easy J友啤!

不用進(jìn)行國際化的控件怎么辦

我們可以添加一個變量來控制代碼是否進(jìn)行國際化誊涯。那就使用關(guān)聯(lián)對象(Associated Object)吧挡毅。

@interface UILabel (NewLabel)
@property (nonatomic, assign)IBInspectable BOOL localizedEnlabe;
@end

@implementation UILabel(NewLabel)

static char *localizedEnlabeChar = "LocalizedEnlabe";

- (void)setLocalizedEnlabe:(BOOL)localizedEnlabe {
    
    objc_setAssociatedObject(self, &localizedEnlabeChar, [NSNumber numberWithBool:localizedEnlabe], OBJC_ASSOCIATION_ASSIGN);
    
}

- (BOOL)localizedEnlabe {
    
    NSNumber *value = objc_getAssociatedObject(self, &localizedEnlabeChar);
    
    if (value) {
        return [value boolValue];
    }
    
    return YES;
    
}

@end

  • 這里我使用 IBInspectable 屬性方便 Xib StoryBoard 設(shè)置屬性.

總結(jié)

這只是個 Demo, 需要國際化的控件還有 UITextField 暴构, UIButton 等控件跪呈。其實(shí)我們這些代碼可以直接在 UIView 的分類中實(shí)現(xiàn)。

然后把我們要處理的屬性方法以同樣的方式 Swizzle 取逾。

雖然這種方法不見得能解決所有問題耗绿,但應(yīng)該是可以解決 80% 的問題的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末砾隅,一起剝皮案震驚了整個濱河市误阻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌晴埂,老刑警劉巖究反,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異邑时,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)特姐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門晶丘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事浅浮∧” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵滚秩,是天一觀的道長专执。 經(jīng)常有香客問我,道長郁油,這世上最難降的妖魔是什么本股? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮桐腌,結(jié)果婚禮上拄显,老公的妹妹穿的比我還像新娘。我一直安慰自己案站,他們只是感情好躬审,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蟆盐,像睡著了一般承边。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上石挂,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天博助,我揣著相機(jī)與錄音,去河邊找鬼誊稚。 笑死翔始,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的里伯。 我是一名探鬼主播城瞎,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼疾瓮!你這毒婦竟也來了脖镀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤狼电,失蹤者是張志新(化名)和其女友劉穎蜒灰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肩碟,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡强窖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了削祈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翅溺。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡脑漫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咙崎,到底是詐尸還是另有隱情优幸,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布褪猛,位于F島的核電站网杆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏伊滋。R本人自食惡果不足惜碳却,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望新啼。 院中可真熱鬧追城,春花似錦、人聲如沸燥撞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽物舒。三九已至色洞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間冠胯,已是汗流浹背火诸。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留荠察,地道東北人置蜀。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像悉盆,于是被迫代替她去往敵國和親盯荤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容