Mantle代碼閱讀一
Mantle是一個能夠簡化我們JSON數據與mocel層面轉換的類庫,在傳統的方法中如果是用手動的轉換工作量較大,技術含量也底。使用該類型的庫能夠簡化代碼邏輯,提高代碼質量。
該類庫中主要有以下幾個關鍵類(協議):
- MTLModel:通常作為我們Model的基類。該類提供了一些默認的行為來處理對象的初始化和歸檔操作,同時可以獲取到對象所有屬性的鍵值集合。
- MTLJSONAdapter:用戶MTLModel與JSON之間的轉換。關鍵點地方,對象和數組的解析的關鍵代碼都在此處。
- MTLJSONSerializing協議:需要與JSON字典進行相互轉換的MTLModel的子類都需要實現該協議,以方便MTLJSONApadter對象進行轉換。此處算是Mantle的核心點之一
- MTLValueTransformer: NSValueTransformer的子類,主要用于數據類型的變換,變換可以是單向或雙向的。
MTLModel
- 該類首先提供了一個初始化方法 - initWithDictionary。當Model中的屬性都是普通數據類型的時候(非NSArray和NSObject),并且屬性名和key完全一樣。我們可以直接用它來初始化。否則無法達到我們的預期。該函數的主要作用在于被MTLJSONAdapter來調用。
- (id)modelFromJSONDictionary:(NSDictionary *)JSONDictionary error:(NSError **)error;
調用MTLModel中的:
+ (instancetype)modelWithDictionary:(NSDictionary *)dictionary error:(NSError **)error
而該類方法調用的就是initWithDictionary了。
- 該類中另外一個關鍵的方法就是+ (NSSet *)propertyKeys; 該方法的定義是由協議MTLModel中繼承而來。該方法能夠取得Model中所有的屬性名稱。
取得的屬性能夠會被緩存到對象中,使用運行時添加到對象中,具體實現代碼如下
+ (NSSet *)propertyKeys {
// 取緩存
NSSet *cachedKeys = objc_getAssociatedObject(self, MTLModelCachedPropertyKeysKey);
if (cachedKeys != nil) return cachedKeys;
NSMutableSet *keys = [NSMutableSet set];
[self enumeratePropertiesUsingBlock:^(objc_property_t property, BOOL *stop) {
NSString *key = @(property_getName(property));
if ([self storageBehaviorForPropertyWithKey:key] != MTLPropertyStorageNone) {
[keys addObject:key];
}
}];
// 添加到對象中,MTLModelCachedPropertyKeysKey不需要有值,只需要地址就OK了。
objc_setAssociatedObject(self, MTLModelCachedPropertyKeysKey, keys, OBJC_ASSOCIATION_COPY);
return keys;
}
同時取得的屬性包含父類中的屬性, 父類一直取到MTLModel得直接子類這一層,如代碼為處理方式:
+ (void)enumeratePropertiesUsingBlock:(void (^)(objc_property_t property, BOOL *stop))block {
Class cls = self;
BOOL stop = NO;
// 控制條件 第二個為只取到MTLModel以下
while (!stop && ![cls isEqual:MTLModel.class]) {
unsigned count = 0;
objc_property_t *properties = class_copyPropertyList(cls, &count);
// 取基類
cls = cls.superclass;
if (properties == NULL) continue;
@onExit {
free(properties);
};
for (unsigned i = 0; i < count; i++) {
block(properties[i], &stop);
if (stop) break;
}
}
}
當然這個類中還有其他很多有趣的地方,比如storageBehaviorForPropertyWithKey該函數中對屬性存儲特性的分析,用到了運行時中很多特性。Mantle中還對整個運行時進行了一定的拓展。
總的來說,該類中主要為用戶提供了Model本身的一些屬性操作,功能的確十分強大。在這個過程中,通過運行時為對象本身關聯了一些屬性,其實也讓對象增加了一些負擔。