介紹
關(guān)于MJExtension的介紹释涛、使用官方已經(jīng)介紹的很清楚了卵渴,請前往Github MJExtension.
MJExtension
這個框架可以快速的進行字典轉(zhuǎn)模型,在實際開發(fā)中非常方便和穩(wěn)定。那么這個框架是如果實現(xiàn)的呢窥妇?
- 這個框架利用了Runtime獲取類的成員屬性就谜。
- 這個框架將所有的成員屬性都封裝成
MJProperty
對象怪蔑。也就是一個成員屬性對應(yīng)著一個MJProperty
的對象。 - 利用Runtime丧荐,對當前類進行一層一層的遍歷缆瓣,當模型類存在繼承關(guān)系時,也是要進行處理的虹统。
- 該框架不僅提供了字典轉(zhuǎn)模型弓坞,也提供了模型轉(zhuǎn)字典中功能。
- 解決了模型嵌套车荔,以及復(fù)雜的模型數(shù)據(jù)問題渡冻。
.....
MJProperty的成員屬性
對于這個類的理解,應(yīng)該是對
propertyKeyDict
和objectClassInArrayDict
的理解和運用忧便,關(guān)于這個下面有詳細的介紹族吻,現(xiàn)在先介紹關(guān)于type(成員屬性的類型)介紹
type(成員屬性的類型)
在該框架中type
也被包裝成了一個MJPropertyType
類型的對象。關(guān)于MJPropertyType
的成員屬性請看下圖珠增。
在
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)成員屬性的描述信息和類型編碼可以查看描述信息巍举、類型編碼。
成員屬性的描述性信息表
聲明的屬性類型編碼表
類型編碼表
以上表格只是參考凝垛,建議去官網(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;
}
輸出
通過上圖的例子,我們可以獲取每個屬性的真實類型定枷,在MJExtension
中有一段代碼就是獲取成員屬性的真實類型孤澎,然后包裝成MJPropertyType
類型的對象
目的就是獲取 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成員屬性的賦值流程
上面有提到關(guān)于propertyKeysDict
和objectClassInArrayDict
成員屬性的理解,這里我采用圖解的方式岖妄,關(guān)于詳細的代碼型将,還請查看官網(wǎng)的詳細代碼。
propertyKeysDict
objectClassInArrayDict
字典轉(zhuǎn)模型
在字典轉(zhuǎn)模型中荐虐,可以初略分為兩大階段
第一是準備階段:
- 將成員屬性包裝成
MJProperty
對象七兜。 - 對象成員屬性type類型的解析和包裝
MJPropertyType
. - 將key 以及多級key的拆分和包裝
MJPropertyKey
. - 以及對
propertyKeysDict
和objectClassInArrayDict
的賦值。
需要注意的是一個類中有多少個成員屬性就會由多少個MJProperty對象福扬,一個MJProperty對象可以擁有多個MJPropertyKey類型的對象(因為key 可能是多級映射)
第二階段是使用階段
- 通過回調(diào)的方式將MJProperty對象返回給外界的核心處理方法腕铸。
- 核心方法采用了通過對類型的判斷采取遞歸的方式進行字典轉(zhuǎn)模型。
- ...
MJEXtension中字典轉(zhuǎn)模型 核心代碼解讀
- (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
- 字典轉(zhuǎn)模型铛碑,傳入的必須是字典狠裹。
- 第一行代碼是對象keyValues的處理,如果傳入的是json字符串或者其他數(shù)據(jù)汽烦,首先需要轉(zhuǎn)換為字典涛菠。
- 第二行代碼是對傳入類型的判斷必須是字典
-
獲取當前類的具體類型,通過類來獲取那些屬性是允許字典轉(zhuǎn)模型撇吞,那些熟悉是不允許字典轉(zhuǎn)模型俗冻。
解讀紅色框住的部分
- 通過上述的介紹我們知道
propertyKeysDict
Value是一個二級數(shù)組 key是具體的類 - 通過類型和成員屬性對象我們就可以通過雙層for得到被包裝的
MJPropertyKey
對象
3.通過MJPropertyKey
對象屬性的name和傳入的字典value
,就可得到內(nèi)層name對應(yīng)的值,此時在將值賦值給value牍颈。(字典可以嵌套字典迄薄,通用模型也可以嵌套模型。這樣就會出現(xiàn)多級key颂砸。在改框架中噪奄,對多級key進行了拆分,但是保留了他們的name人乓,通過那么就可以在最外層的字段中查找對應(yīng)的值了) - 最后對value值的過濾勤篮,以及判空處理。
- 獲取該成員屬性的類型色罚。
- 判斷是否是一個類作為成員屬性碰缔。
- 模型數(shù)據(jù)的具體類型。
- 標記為1的部分判斷
MJProperty *property
是否是Foundation 類型 并且propertyClass
確實存在一個類作為成員屬性戳护,那么就進行遞歸金抡,再次調(diào)用高方法瀑焦。 - 標記為2的部分是處理模型數(shù)組作為成員屬性的。
最后一步是通過KVC進行賦值梗肝。
另外MJExtension提供了模型轉(zhuǎn)字典榛瓮,后續(xù)....