YYModel 原始碼分析 字典轉模型

2021-10-22 05:36:07 字數 3784 閱讀 4440

有這麼個模型

@inte***ce author : nsobject

@property nsstring *name;

@property nsstring *birthday;

@end

@inte***ce book : nsobject

@property nsstring *name;

@property nsuinteger pages;

@property author *author;

@end

建立的一般流程是這樣的

book * page = [book new];

page.name = @"天書";

page.pages = 245;

author * writer = [author new];

writer.name = @"孫大聖";

writer.birthday = @"不曉得";

page.author = writer;

使用 yymodel 後,可以這樣

nsstring * path = [nsbundle.mainbundle pathforresource: @"one" oftype: @"json"];

nsstring* jsonstring = [[nsstring alloc] initwithcontentsoffile:path encoding:nsutf8stringencoding error:nil];

nsdata* jsondata = [jsonstring datausingencoding:nsutf8stringencoding];

book * page = [book yy_modelwithjson: jsondata];

yymodel 通過執行時,把我們手動的部分,自動化了

然後實現自動賦值

對其源**,有簡化

yymodel 的方法實現,

是對 nsobject,加擴充套件

@inte***ce nsobject (yymodel)

@end

拿到資料,吐出模型

+ (instancetype)yy_modelwithjson:(id)json
給字典,拿到模型的方法

+ (instancetype)yy_modelwithdictionary:(nsdictionary *)dictionary
其中,這一行

nsobject *one = [cls new];
對應

book * page = [book new];
小結,yymodel 並不神奇,做的事情,也就是建立模型,給模型的屬性填資料

給模型填資料

- (bool)yy_modelsetwithdictionary:(nsdictionary *)dic ;

context.modelmeta = (__bridge void *)(modelmeta);

context.model = (__bridge void *)(self);

context.dictionary = (__bridge void *)(dic);

// 對字典的每乙個鍵值,批量呼叫 modelsetwithdictionaryfunction 方法

// ...

// 省略兩個 if

} else

return yes;

}

進入屬性賦值方法modelsetwithdictionaryfunction

static void modelsetwithdictionaryfunction(const void *_key, const void *_value, void *_context)
進入具體賦值方法modelsetvalueforproperty

對於整型的值,手段類似

呼叫yy_modelsetwithdictionary,上面的流程,重新來一遍

遞迴的呼叫出現了

// 下面的方法,有大幅簡化,僅用於舉例

static void modelsetvalueforproperty(__unsafe_unretained id model,

__unsafe_unretained id value,

__unsafe_unretained _yymodelpropertymeta *meta)

} break;

default: break;

}} else else if ([value iskindofclass:cls] || !cls) else if ([value iskindofclass:[nsdictionary class]])

} break;

default: break;}}

}

上面的這一句

[cls new];
對應開頭部分

author * writer = [author new];
流程就走完了

**接著看

給乙個 json, 拿到字典,

這個 json ,可以是字串、字典、二進位制資料 nsdata

這邊都做了相應的檢查,和處理

+ (nsdictionary *)_yy_dictionarywithjson:(id)json  else if ([json iskindofclass:[nsstring class]])  else if ([json iskindofclass:[nsdata class]]) 

if (jsondata)

return dic;

}

通過執行時,拿到屬性資訊

入口是,這一句

_yymodelmeta *modelmeta = [_yymodelmeta metawithclass:object_getclass(self)];
進入這個類_yymodelmeta

初始化方法, 看起來嚇人,

又是單例、鎖、訊號量

實際很簡單

有用的**,只有一行

meta = [[_yymodelmeta alloc] initwithclass:cls];
建立兩個單例,快取,和一把鎖,實際是訊號量

然後獲取meta,

有快取,取快取

沒快取,去建立

通過訊號量這把鎖,保證快取操作,是執行緒安全的

+ (instancetype)metawithclass:(class)cls );

dispatch_semaphore_wait(lock, dispatch_time_forever);

_yymodelmeta *meta = cfdictionarygetvalue(cache, (__bridge const void *)(cls));

dispatch_semaphore_signal(lock);

if (!meta)

}return meta;

}

執行時相關,下篇繼續

YYModel 原始碼分析

instancetype yy modelwithdictionary nsdictionary dictionary 第一步 準備 yymodelmeta 類 分析 1.cache快取 yymodelmeta 類,如果乙個模型已經轉換過,就會儲存到cache裡面,如果下次遇到相同的model,就會...

YYModel原始碼閱讀(一)

專案中一直在使用yymodel來進行model的轉換。自己閱讀了yymodel的原始碼,下面就從最基本的開始對yymodel進行分析。標頭檔案yymodel if has include foundation export double yymodelversionnumber foundation...

YYModel 原始碼解讀(一)之YYModel h

if has include foundation export double yymodelversionnumber foundation export const unsigned char yymodelversionstring import import else import nsob...