利用RunTime做一點(diǎn)點(diǎn)代碼優(yōu)化記錄

現(xiàn)狀

業(yè)務(wù)這邊之前有需求各種config脂倦,從后端拿到數(shù)據(jù)番宁,一個(gè)字典挨個(gè)解析。
最早的寫(xiě)法如下:

...
    NSNumber* xxxx = [infoDic objectForKey:@"xxxx"];
    if (xxxx != nil && [xxxx isKindOfClass:[NSNumber class]]) {// or [NSString class]
        int nRateDialog = [xxxx intValue];
        if (nRateDialog == 1) {
            infoModel.xxxx = YES;
        }else{
            infoModel.xxxx = NO;
        }
    }
** 很多類似的寫(xiě)法
...

代碼臃腫不說(shuō)狼讨,很丑贝淤。

但是柒竞,因?yàn)樯瞎虐姹镜脑蛘愔卸x的數(shù)據(jù)類型也是隨心所欲。

int NSInteger NSString NSNumber BOOL float CGFloat

幾乎包含了所有的能用到的類型...
再加上這邊要給QA做一個(gè)開(kāi)關(guān)的需求朽基,本地隨便修改這些config布隔。所有有了這篇記錄。
當(dāng)然如果你本身代碼很規(guī)范稼虎,直接用Mantle或者其他的工具解析就完事了衅檀。我這邊因?yàn)槭巧瞎糯a的關(guān)系,不可能直接修改改動(dòng)太大霎俩,所以才出此下策哀军。

大概思路

  1. 后端或者本地緩存拿到數(shù)據(jù)。
  2. 如果是QA環(huán)境需要檢查本地的debug數(shù)據(jù)打却,看是否設(shè)置過(guò)本地的config杉适,如果設(shè)置過(guò)則需要將debug數(shù)據(jù)更新上去。
  3. 通過(guò)便利拿到的數(shù)據(jù)通過(guò)key值通過(guò)runtimeobject_setIvar一一對(duì)應(yīng)的設(shè)給對(duì)應(yīng)的Model柳击。

難點(diǎn)一

  1. 代碼里面的屬性名稱跟后端的Key對(duì)不上猿推。
    比如,后端的key是TestKey,但是代碼里面的屬性名稱是1111蹬叭。(只是比喻)
  2. 有一些config在設(shè)計(jì)的時(shí)候不是按照一個(gè)規(guī)范來(lái)的藕咏。需要對(duì)這個(gè)config做一個(gè)特殊的處理。

難點(diǎn)解決

  1. 照著Mantle的模式寫(xiě)了一個(gè)方法返回一個(gè)字典秽五。對(duì)應(yīng)的Key孽查、Value分別是后端的Key以及本地的屬性名稱。
  2. 另外一個(gè)方法坦喘,返回的是需要特殊處理的key卦碾。

這樣寫(xiě)的好處是便于后續(xù)擴(kuò)展。
如果真的需要兩端不相同起宽,只需在1方法中加上對(duì)應(yīng)的Key洲胖、Value就行。如果需要特殊處理只需在2加對(duì)應(yīng)的值就行坯沪。并且绿映,后續(xù)添加config只需.h 方法中新增就行,無(wú)需多加代碼腐晾,提高效率叉弦。

難點(diǎn)二

在寫(xiě)代碼過(guò)程中,發(fā)現(xiàn)runtime的方法object_setIvar設(shè)值的問(wèn)題藻糖。

object_setIvar(id _Nullable obj, Ivar _Nonnull ivar, id _Nullable value)

object_setIvar 需要傳三個(gè)值淹冰。 obj是你要賦值的對(duì)象。ivar是你通過(guò)屬性名拿到的指針巨柒。value是你要設(shè)置的值

無(wú)論你是百度還是Google樱拴,你搜到的runtime相關(guān)教程在這里設(shè)置的都是一個(gè)string或者其他對(duì)象。但是int洋满,NSInteger晶乔,float或者CGFloat它不是一個(gè)對(duì)象,如果你直接設(shè)置就會(huì)報(bào)錯(cuò)牺勾。

所以又是一番查找正罢,最后發(fā)現(xiàn)了解決方式。下面是stackoverflow鏈接驻民。
stackoverflow

直接通過(guò)指針投射過(guò)去翻具! NB

至此,所有難點(diǎn)就攻克回还。代碼什么的隨便寫(xiě)寫(xiě)就完事裆泳,重點(diǎn)是思路以及runtime相關(guān)知識(shí)。

更重要的是把之前快1000行的垃圾代碼優(yōu)化到了200多行懦趋,如果所有的規(guī)范統(tǒng)一的話100行甚至更少

runtime這邊拿到的屬性值晾虑。需要記錄一下

BOOL -> TB
int -> Ti
NSNumber -> T@"NSNumber"
NSString -> T@"NSString"
NSInteger -> Tq
NSArray -> T@"NSArray"
id -> T@
float -> Tf
CGFloat -> Td

如果屬性是一個(gè)枚舉(NS_ENUM),那么你拿到的是你枚舉對(duì)應(yīng)的值。
比如:

typedef NS_ENUM(NSInteger, TestStyle) {

};
拿到的就是Tq帜篇。

7-9 Update:

void (*object_setIvarFloat)(id, Ivar, CGFloat) = (void (*)(id, Ivar, CGFloat))object_setIvar;

使用這種方式莫名的會(huì)出現(xiàn)賦值無(wú)法成功的情況糙捺。
最終還是選擇了如果是int這種情況直接采用拿對(duì)應(yīng)屬性的地址偏移量直接賦值,下面是代碼:

void setIvarMethod1 (const char * type, id n, Ivar ivar, NSString *obj) {
    ptrdiff_t offset = ivar_getOffset(ivar);
    unsigned char *stuffBytes = (unsigned char *)(__bridge void *)n;
    
    if (strcmp(type, "B") == 0) {
        *((BOOL *)(stuffBytes + offset)) = obj.boolValue;
    }else if (strcmp(type, "q") == 0){
        *((NSInteger *)(stuffBytes + offset)) = obj.integerValue;
    }else if (strcmp(type, "i") == 0) {
        *((int *)(stuffBytes + offset)) = obj.intValue;
    }else if (strcmp(type, "d") == 0 || strcmp(type, "f") == 0){
        *((float *)(stuffBytes + offset)) = obj.floatValue;
    }else{
        object_setIvar(n, ivar, obj);
    }
}

后續(xù)繼續(xù)跟進(jìn)結(jié)果笙隙。如果有問(wèn)題會(huì)繼續(xù)更新

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洪灯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子竟痰,更是在濱河造成了極大的恐慌签钩,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坏快,死亡現(xiàn)場(chǎng)離奇詭異铅檩,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)莽鸿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)昧旨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人祥得,你說(shuō)我怎么就攤上這事兔沃。” “怎么了级及?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵乒疏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我饮焦,道長(zhǎng)怕吴,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任追驴,我火速辦了婚禮械哟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘殿雪。我一直安慰自己,他們只是感情好锋爪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布丙曙。 她就那樣靜靜地躺著,像睡著了一般其骄。 火紅的嫁衣襯著肌膚如雪亏镰。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,829評(píng)論 1 290
  • 那天拯爽,我揣著相機(jī)與錄音索抓,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛逼肯,可吹牛的內(nèi)容都是我干的耸黑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼篮幢,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼大刊!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起三椿,我...
    開(kāi)封第一講書(shū)人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缺菌,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后搜锰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體伴郁,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年蛋叼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛾绎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸦列,死狀恐怖租冠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情薯嗤,我是刑警寧澤顽爹,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站骆姐,受9級(jí)特大地震影響镜粤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜玻褪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一肉渴、第九天 我趴在偏房一處隱蔽的房頂上張望访惜。 院中可真熱鬧融欧,春花似錦、人聲如沸咧擂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至灿里,卻和暖如春关炼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背匣吊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工儒拂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寸潦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓社痛,卻偏偏與公主長(zhǎng)得像见转,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子褥影,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349