解讀MJExtension

介紹

關(guān)于MJExtension的介紹释涛、使用官方已經(jīng)介紹的很清楚了卵渴,請前往Github MJExtension.

MJExtension

這個框架可以快速的進行字典轉(zhuǎn)模型,在實際開發(fā)中非常方便和穩(wěn)定。那么這個框架是如果實現(xiàn)的呢窥妇?

  1. 這個框架利用了Runtime獲取類的成員屬性就谜。
  2. 這個框架將所有的成員屬性都封裝成MJProperty對象怪蔑。也就是一個成員屬性對應(yīng)著一個MJProperty的對象。
  3. 利用Runtime丧荐,對當前類進行一層一層的遍歷缆瓣,當模型類存在繼承關(guān)系時,也是要進行處理的虹统。
  4. 該框架不僅提供了字典轉(zhuǎn)模型弓坞,也提供了模型轉(zhuǎn)字典中功能。
  5. 解決了模型嵌套车荔,以及復(fù)雜的模型數(shù)據(jù)問題渡冻。
    .....

MJProperty的成員屬性

image.png

對于這個類的理解,應(yīng)該是對propertyKeyDictobjectClassInArrayDict的理解和運用忧便,關(guān)于這個下面有詳細的介紹族吻,現(xiàn)在先介紹關(guān)于type(成員屬性的類型)介紹

type(成員屬性的類型)

在該框架中type也被包裝成了一個MJPropertyType類型的對象。關(guān)于MJPropertyType的成員屬性請看下圖珠增。

image.png

MJPropertyType.m文件中我們會看到以下的一行代碼

NSArray *numberTypes = @[MJPropertyTypeInt,MJPropertyTypeShort, MJPropertyTypeBOOL1, MJPropertyTypeBOOL2, MJPropertyTypeFloat, MJPropertyTypeDouble, MJPropertyTypeLong, MJPropertyTypeLongLong, MJPropertyTypeChar];
/**
*  成員變量類型(屬性類型)
*/
NSString *const MJPropertyTypeInt = @"i";
NSString *const MJPropertyTypeShort = @"s";
NSString *const MJPropertyTypeFloat = @"f";
NSString *const MJPropertyTypeDouble = @"d";
NSString *const MJPropertyTypeLong = @"l";
NSString *const MJPropertyTypeLongLong = @"q";
NSString *const MJPropertyTypeChar = @"c";
NSString *const MJPropertyTypeBOOL1 = @"c";
NSString *const MJPropertyTypeBOOL2 = @"b";
NSString *const MJPropertyTypePointer = @"*";

NSString *const MJPropertyTypeIvar = @"^{objc_ivar=}";
NSString *const MJPropertyTypeMethod = @"^{objc_method=}";
NSString *const MJPropertyTypeBlock = @"@?";
NSString *const MJPropertyTypeClass = @"#";
NSString *const MJPropertyTypeSEL = @":";
NSString *const MJPropertyTypeId = @"@";

上述代碼定義的是成員屬性的類型編碼超歌,我們可以通過Runtime提供的const char * property_getAttributes(objc_property_t property)api來可以獲取成員屬性的描述信息,其中就包含了類型編碼蒂教。
有關(guān)成員屬性的描述信息和類型編碼可以查看描述信息巍举、類型編碼

成員屬性的描述性信息表


image.png

聲明的屬性類型編碼表


image.png

類型編碼表

image.png

以上表格只是參考凝垛,建議去官網(wǎng)查詢描述信息懊悯、類型編碼蜓谋。

舉個例子

@interface MLStudent : NSObject
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) int age;
@property (assign, nonatomic) double weight;
@property (assign, nonatomic) double height;
@property (assign, nonatomic) struct objc_method *Method;
@property (assign, nonatomic) struct objc_ivar *Ivar;
@property (assign, nonatomic) void(^block)(void);
@property (strong, nonatomic) MLCar* myCar;

@end
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        unsigned int count;
        objc_property_t * property_ts =class_copyPropertyList([MLStudent class], &count);
        for (int i = 0; i < count; i ++) {
            objc_property_t  property_t  = property_ts[i];
   
          const char *  propertyAttributes_c =  property_getAttributes(property_t);
            NSString *propertyAttributes =  [[NSString alloc] initWithUTF8String:propertyAttributes_c];
            NSLog(@"Attributes:  %@",propertyAttributes);
            
           
            NSUInteger dotLoc = [propertyAttributes rangeOfString:@","].location;
            NSString *code = nil;
            NSUInteger loc = 1;
            if (dotLoc == NSNotFound) { // 沒有,
                code = [propertyAttributes substringFromIndex:loc];
            } else {
                code = [propertyAttributes substringWithRange:NSMakeRange(loc, dotLoc - loc)];
            }
            NSLog(@"code: %@",code);
          
        }
        
    }
    return 0;
}

輸出


image.png
image.png

通過上圖的例子,我們可以獲取每個屬性的真實類型定枷,在MJExtension中有一段代碼就是獲取成員屬性的真實類型孤澎,然后包裝成MJPropertyType類型的對象

image.png

目的就是獲取 T后面的真實類型

T@"NSString",C,N,V_name

  • @"NSString":代表NSString類型,
  • C :代表采用copy策略
  • N :代表nonatomic非原子性
  • V_name : 代表name成員屬性的名字

Ti,N,V_age

  • i:代表int類型
  • N:代表nonatomic非原子性
  • V_age:代表age成員屬性的名字
    關(guān)于下面的類型里面的代碼欠窒,代碼里面介紹以及很詳細了覆旭。

MJProperty成員屬性的賦值流程

image.png

上面有提到關(guān)于propertyKeysDictobjectClassInArrayDict成員屬性的理解,這里我采用圖解的方式岖妄,關(guān)于詳細的代碼型将,還請查看官網(wǎng)的詳細代碼。
propertyKeysDict

image.png

objectClassInArrayDict
image.png

字典轉(zhuǎn)模型

image.png

在字典轉(zhuǎn)模型中荐虐,可以初略分為兩大階段

第一是準備階段

  1. 將成員屬性包裝成MJProperty對象七兜。
  2. 對象成員屬性type類型的解析和包裝MJPropertyType.
  3. 將key 以及多級key的拆分和包裝MJPropertyKey.
  4. 以及對propertyKeysDictobjectClassInArrayDict的賦值。
    需要注意的是一個類中有多少個成員屬性就會由多少個MJProperty對象福扬,一個MJProperty對象可以擁有多個MJPropertyKey類型的對象(因為key 可能是多級映射)

第二階段是使用階段

  1. 通過回調(diào)的方式將MJProperty對象返回給外界的核心處理方法腕铸。
  2. 核心方法采用了通過對類型的判斷采取遞歸的方式進行字典轉(zhuǎn)模型。
  3. ...

MJEXtension中字典轉(zhuǎn)模型 核心代碼解讀

- (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context

image.png

  1. 字典轉(zhuǎn)模型铛碑,傳入的必須是字典狠裹。
  2. 第一行代碼是對象keyValues的處理,如果傳入的是json字符串或者其他數(shù)據(jù)汽烦,首先需要轉(zhuǎn)換為字典涛菠。
  3. 第二行代碼是對傳入類型的判斷必須是字典
  4. 獲取當前類的具體類型,通過類來獲取那些屬性是允許字典轉(zhuǎn)模型撇吞,那些熟悉是不允許字典轉(zhuǎn)模型俗冻。


    image.png

解讀紅色框住的部分

  1. 通過上述的介紹我們知道propertyKeysDict Value是一個二級數(shù)組 key是具體的類
  2. 通過類型和成員屬性對象我們就可以通過雙層for得到被包裝的MJPropertyKey對象
    3.通過MJPropertyKey對象屬性的name和傳入的字典value,就可得到內(nèi)層name對應(yīng)的值,此時在將值賦值給value牍颈。(字典可以嵌套字典迄薄,通用模型也可以嵌套模型。這樣就會出現(xiàn)多級key颂砸。在改框架中噪奄,對多級key進行了拆分,但是保留了他們的name人乓,通過那么就可以在最外層的字段中查找對應(yīng)的值了)
  3. 最后對value值的過濾勤篮,以及判空處理。
image.png
  1. 獲取該成員屬性的類型色罚。
  2. 判斷是否是一個類作為成員屬性碰缔。
  3. 模型數(shù)據(jù)的具體類型。
image.png
  1. 標記為1的部分判斷MJProperty *property是否是Foundation 類型 并且propertyClass確實存在一個類作為成員屬性戳护,那么就進行遞歸金抡,再次調(diào)用高方法瀑焦。
  2. 標記為2的部分是處理模型數(shù)組作為成員屬性的。
image.png

最后一步是通過KVC進行賦值梗肝。

另外MJExtension提供了模型轉(zhuǎn)字典榛瓮,后續(xù)....

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市巫击,隨后出現(xiàn)的幾起案子禀晓,更是在濱河造成了極大的恐慌,老刑警劉巖坝锰,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粹懒,死亡現(xiàn)場離奇詭異,居然都是意外死亡顷级,警方通過查閱死者的電腦和手機凫乖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弓颈,“玉大人帽芽,你說我怎么就攤上這事∠杓剑” “怎么了嚣镜?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長橘蜜。 經(jīng)常有香客問我,道長付呕,這世上最難降的妖魔是什么计福? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮徽职,結(jié)果婚禮上象颖,老公的妹妹穿的比我還像新娘。我一直安慰自己姆钉,他們只是感情好说订,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著潮瓶,像睡著了一般陶冷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上毯辅,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天埂伦,我揣著相機與錄音,去河邊找鬼思恐。 笑死沾谜,一個胖子當著我的面吹牛膊毁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播基跑,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼婚温,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了媳否?” 一聲冷哼從身側(cè)響起栅螟,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逆日,沒想到半個月后嵌巷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡室抽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年搪哪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坪圾。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡晓折,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兽泄,到底是詐尸還是另有隱情漓概,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布病梢,位于F島的核電站胃珍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蜓陌。R本人自食惡果不足惜觅彰,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钮热。 院中可真熱鬧填抬,春花似錦、人聲如沸隧期。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仆潮。三九已至宏蛉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸵闪,已是汗流浹背檐晕。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辟灰。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓个榕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親芥喇。 傳聞我的和親對象是個殘疾皇子西采,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

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

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,096評論 1 32
  • 在日常的iOS開發(fā)中,總會進行數(shù)據(jù)的轉(zhuǎn)換继控,比如請求服務(wù)端獲取數(shù)據(jù)械馆,解析數(shù)據(jù),轉(zhuǎn)換成對應(yīng)的model武通,這個轉(zhuǎn)換過...
    繁星mind閱讀 13,943評論 7 49
  • MJExtension A fast, convenient and nonintrusive conversio...
    雪山飛狐_91ae閱讀 1,555評論 0 13
  • 什么是runtime霹崎? runtime 是 OC底層的一套C語言的API(引入 <objc/runtime.h>或...
    木子奕閱讀 1,599評論 0 16
  • 前言 runtime的資料網(wǎng)上有很多了,部分有些晦澀難懂冶忱,我通過自己的學(xué)習方法總結(jié)一遍尾菇,主要講一些常用的方法功能,...
    YinLei閱讀 309評論 0 0