【移動(dòng)應(yīng)用開發(fā)技術(shù)】從YYModel源碼中可以學(xué)到什么:后篇_第1頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】從YYModel源碼中可以學(xué)到什么:后篇_第2頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】從YYModel源碼中可以學(xué)到什么:后篇_第3頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】從YYModel源碼中可以學(xué)到什么:后篇_第4頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】從YYModel源碼中可以學(xué)到什么:后篇_第5頁(yè)
已閱讀5頁(yè),還剩5頁(yè)未讀 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開發(fā)技術(shù)】從YYModel源碼中可以學(xué)到什么:后篇

上一篇中《從YYModel源碼中可以學(xué)到什么:后篇》中主要學(xué)習(xí)了YYModel的源碼結(jié)構(gòu),只是分享了YYModel整體結(jié)構(gòu)。承接上篇,本文將解讀YYModel如何進(jìn)行JSON模型轉(zhuǎn)換的,接下來(lái)一起揭開YYModel的神秘面紗吧!首先來(lái)看JSON是如何轉(zhuǎn)為Model。查看YYModel的接口,提供了一個(gè)方法:+(instancetype)yy_modelWithJSON:(id)json;注意json為id類型,接收三種不同類型參數(shù)NSString,NSData,NSDictionay。下面是內(nèi)部實(shí)現(xiàn):+(instancetype)yy_modelWithJSON:(id)json{

NSDictionary*dic=[self_yy_dictionaryWithJSON:json];

return[selfyy_modelWithDictionary:dic];

}方法中調(diào)用了一個(gè)私有方法_yy_dictionaryWithJSON:,該方法將id類型的json(NSDictionary,NSString,NSData)轉(zhuǎn)為字典。+(NSDictionary*)_yy_dictionaryWithJSON:(id)json{

//驗(yàn)證json

if(!json||json==(id)kCFNull)returnnil;

//兩個(gè)臨時(shí)變量

NSDictionary*dic=nil;

NSData*jsonData=nil;

//根據(jù)json類型,進(jìn)行相應(yīng)處理

if([jsonisKindOfClass:[NSDictionaryclass]]){

dic=json;

}elseif([jsonisKindOfClass:[NSStringclass]]){

jsonData=[(NSString*)jsondataUsingEncoding:NSUTF8StringEncoding];

}elseif([jsonisKindOfClass:[NSDataclass]]){

jsonData=json;

}

//使用NSJSONSerialization將Data轉(zhuǎn)為字典

if(jsonData){

dic=[NSJSONSerializationJSONObjectWithData:jsonDataoptions:kNilOptionserror:NULL];

if(![dicisKindOfClass:[NSDictionaryclass]])dic=nil;

}

returndic;

}

該方法很簡(jiǎn)單,就是判斷id類型是指(NSDictionary,NSString,NSData)中的哪一個(gè),分別處理。

在json==(id)kCFNull中kCFNull是什么意思?這條語(yǔ)句起到什么作用?

nil:指向OC中對(duì)象的空指針

Nil:指向OC中類的空指針

NULL:定義其他類型(基本類型、C類型)的空指針

NSNull:集合對(duì)象中,表示空值的對(duì)象。如給數(shù)組設(shè)置空值,使用NSNull,而不能使用nil。

kCFNull是NSNull的單例。

if(!json||json==(id)kCFNull)returnnil;該判斷的意思是,json對(duì)象不存在,或者為空是返回nil。

該方法很簡(jiǎn)單,就是判斷id類型是指(NSDictionary,NSString,NSData)中的哪一個(gè),分別處理。在json==(id)kCFNull中kCFNull是什么意思?這條語(yǔ)句起到什么作用?nil:指向OC中對(duì)象的空指針Nil:指向OC中類的空指針NULL:定義其他類型(基本類型、C類型)的空指針NSNull:集合對(duì)象中,表示空值的對(duì)象。如給數(shù)組設(shè)置空值,使用NSNull,而不能使用nil。kCFNull是NSNull的單例。if(!json||json==(id)kCFNull)returnnil;該判斷的意思是,json對(duì)象不存在,或者為空是返回nil。獲取到字典后,調(diào)用字典轉(zhuǎn)Model方法:+(nullableinstancetype)yy_modelWithDictionary:(NSDictionary*)dictionary此方法也是在.h文件中暴露出來(lái)的方法。接下來(lái)查看具體實(shí)現(xiàn):/**

字典轉(zhuǎn)model

@paramdictionary字典

@return返回Model對(duì)象

*/

+(instancetype)yy_modelWithDictionary:(NSDictionary*)dictionary{

//1.驗(yàn)證,空值,nil和是否是字典

if(!dictionary||dictionary==(id)kCFNull)returnnil;

if(![dictionaryisKindOfClass:[NSDictionaryclass]])returnnil;

Classcls=[selfclass];

//2.創(chuàng)建一個(gè)YYModelMeta對(duì)象

_YYModelMeta*modelMeta=[_YYModelMetametaWithClass:cls];

//判斷是否需要自定義返回模型的類型,這是YYModel協(xié)議中的內(nèi)容,算是附加功能暫時(shí)先忽略,后面在介紹。

if(modelMeta->_hasCustomClassFromDictionary){

cls=[clsmodelCustomClassForDictionary:dictionary]?:cls;

}

//3.創(chuàng)建model對(duì)象

NSObject*one=[clsnew];

//4.關(guān)鍵方法

if([oneyy_modelSetWithDictionary:dictionary])

returnone;

returnnil;

}這個(gè)方法主要的任務(wù)是調(diào)用了yy_modelSetWithDictionary:方法。這個(gè)方法也是在.h文件中暴露的,它的作用是根據(jù)字典初始化模型。代碼實(shí)現(xiàn):-(BOOL)yy_modelSetWithDictionary:(NSDictionary*)dic{

//1.值和類型驗(yàn)證

if(!dic||dic==(id)kCFNull)returnNO;

if(![dicisKindOfClass:[NSDictionaryclass]])returnNO;

//2.創(chuàng)建Modelmeta對(duì)象

_YYModelMeta*modelMeta=[_YYModelMetametaWithClass:object_getClass(self)];

//屬性個(gè)數(shù),如為零返回。創(chuàng)建失敗

if(modelMeta->_keyMappedCount==0)returnNO;

//YYModel協(xié)議,暫且忽略

if(modelMeta->_hasCustomWillTransformFromDictionary){

dic=[((id<YYModel>)self)modelCustomWillTransformFromDictionary:dic];

if(![dicisKindOfClass:[NSDictionaryclass]])returnNO;

}

//3.創(chuàng)建結(jié)構(gòu)體

ModelSetContextcontext={0};

context.modelMeta=(__bridgevoid*)(modelMeta);

context.model=(__bridgevoid*)(self);

context.dictionary=(__bridgevoid*)(dic);

//模型元值數(shù)量和字典數(shù)量關(guān)系

//1.通常情況是兩者相等,

//2.模型元鍵值少于字典個(gè)數(shù)

if(modelMeta->_keyMappedCount>=CFDictionaryGetCount((CFDictionaryRef)dic)){

//調(diào)用ModelSetWithDictionaryFunction方法,這是核心方法。

//參數(shù):

//1.要操作的字典

//2.為每個(gè)鍵值對(duì)調(diào)用一次的回調(diào)函數(shù)

//3.指針大小的程序定義的值,作為第三個(gè)參數(shù)傳遞給應(yīng)用程序函數(shù),但此函數(shù)未使用該值.與參數(shù)2適應(yīng)

CFDictionaryApplyFunction((CFDictionaryRef)dic,ModelSetWithDictionaryFunction,&context);

//是否存在映射keyPath屬性元

if(modelMeta->_keyPathPropertyMetas){

//每個(gè)keypath都執(zhí)行ModelSetWithPropertyMetaArrayFunction

CFArrayApplyFunction((CFArrayRef)modelMeta->_keyPathPropertyMetas,

CFRangeMake(0,CFArrayGetCount((CFArrayRef)modelMeta->_keyPathPropertyMetas)),

ModelSetWithPropertyMetaArrayFunction,

&context);

}

//是否存在映射多個(gè)key的屬性元

if(modelMeta->_multiKeysPropertyMetas){

//每個(gè)keypath都執(zhí)行ModelSetWithPropertyMetaArrayFunction

CFArrayApplyFunction((CFArrayRef)modelMeta->_multiKeysPropertyMetas,

CFRangeMake(0,CFArrayGetCount((CFArrayRef)modelMeta->_multiKeysPropertyMetas)),

ModelSetWithPropertyMetaArrayFunction,

&context);

}

}else{

//每個(gè)keypath都執(zhí)行ModelSetWithPropertyMetaArrayFunction

CFArrayApplyFunction((CFArrayRef)modelMeta->_allPropertyMetas,

CFRangeMake(0,modelMeta->_keyMappedCount),

ModelSetWithPropertyMetaArrayFunction,

&context);

}

//忽略

if(modelMeta->_hasCustomTransformFromDictionary){

return[((id<YYModel>)self)modelCustomTransformFromDictionary:dic];

}

returnYES;

}

上面注釋該方法大致干了幾件事。關(guān)于ModelSetContext是一個(gè)結(jié)構(gòu)體。包含模型元,模型實(shí)例和待處理字典。typedefstruct{

void*modelMeta;///<_YYModelMeta

void*model;///<id(self)

void*dictionary;///<NSDictionary(json)

}ModelSetContext;通過上面的分析,線路越來(lái)越清晰,下面看一下核心方法ModelSetWithDictionaryFunction將字典的鍵值對(duì)取出賦值給Model。//獲取到字典的鍵值對(duì),和上下文信息。

staticvoidModelSetWithDictionaryFunction(constvoid*_key,constvoid*_value,void*_context){

//上下文,包含模型元,模型實(shí)例,字典

ModelSetContext*context=_context;

//模型元

__unsafe_unretained_YYModelMeta*meta=(__bridge_YYModelMeta*)(context->modelMeta);

//在模型元屬性字典中查找鍵值為key的屬性

__unsafe_unretained_YYModelPropertyMeta*propertyMeta=[meta->_mapperobjectForKey:(__bridgeid)(_key)];

//模型實(shí)例

__unsafe_unretainedidmodel=(__bridgeid)(context->model);

//核心內(nèi)容,遍歷所有的屬性元。知道_next=nil

while(propertyMeta){

if(propertyMeta->_setter){

//最終轉(zhuǎn)換(高潮)

ModelSetValueForProperty(model,(__bridge__unsafe_unretainedid)_value,propertyMeta);

}

propertyMeta=propertyMeta->_next;

};

}該方法主要任務(wù)是,遍歷所有的屬性元,調(diào)用模型屬性賦值方法ModelSetValueForProperty。最終實(shí)現(xiàn)。也就是YYModel的最最最核心的部分。不過,這個(gè)方法長(zhǎng)的離譜。由于涉及到較多的編碼類型,需要對(duì)不同的類型區(qū)分處理,導(dǎo)致代碼過長(zhǎng)。由于ModelSetValueForPorperty代碼較長(zhǎng),這里不再?gòu)?fù)制代碼。只梳理一下實(shí)現(xiàn)的邏輯,注釋代碼在Github自行查閱。調(diào)用ModelSetNumberToPorperty方法,該方法作用是:識(shí)別null、bool、123.

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論