原文:http://www.cnblogs.com/lujianwenance/p/5706548.html
本文主要是對YYModel文件結構的簡單分析,能幫助你更快的熟悉和學習YYModel。如有問題,希望能指正,謝謝。
一、YYCLassInfo文件
YYClassIVarInfo:存放變量的Model
YYClassMethodInfo:存放方法的Model
YYClassPropertyInfo:存放property的Model
YYClassInfo:存放類信息的Model
YYClassIvarInfo:通過Ivar來初始化,賦值相應的需要保存的字段,比較簡單。
YYClassMethodInfo:通過Method來初始化,跟Ivar不同的是,typeEncoding有兩個,一個是參數的,一個是返回值的。打印了一個例子,如下圖:

分別是參數和返回值的typeEncoding、返回值的、參數的
YYClassPropertyInfo:通過objc_property_t來初始化,保存一些相關的信息。
YYClassInfo:可以通過Class,也可以使用NSString * className來初始化,保存相關類的信息。
二、NSObject+YYModel文件
這個文件是YYModel的核心,提供了一些,son轉model、字典轉model、model轉NSData、model轉Json等方法。
1、兩個model,一個是_YYModelPropertyMeta、一個是_YYModelMeta。
_YYModelPropertyMeta:
是對YYClassPropertyInfo的進一步封裝,加入了一些操作性的或者說是功能性的封裝。比如是否是C number type、是否支持KVC、是否可以被歸檔、是否有自定義的映射字典等等。還有一個比較特殊的是next,next是指向下一個_YYModelPropertyMeta的指針,他是用來處理多個屬性映射到同一個key上時使用的。
_YYModelMeta:
是對YYClassInfo一層解析,映射了每個property的key對應的_YYModelPropertyMeta——>mapper、所有的_YYModelPropertyMeta——>allPropertyMetas、所有的解析了keyPath的_YYModelPropertyMeta——>keyPathPropertyMetas、多個key對應的_YYModelPropertyMeta——>multiKeysPropertyMetas、映射了mapper.count——>keyMappedCount、Model class type ——> nsType、以及這個model是否實現了支持dic轉model,轉成dic和dic轉class。
2、內聯函數
1)YYClassGetNSType:獲取Class的Foundation class type
2)YYEncodingTypeIsCNumber:判斷YYEncodingType是否是C number(常用數據類型)
3)YYNSNumberCreateFromID:把一個id類型的值轉換成NSNumber類型,這個函數主要是處理string類型的數據。其中使用到了幾個c函數,分別如下:
atop(const char *cstring)返回一個double類型,轉換string為double
isnan(double num) 確定是不是一個數,是否是無窮大或無窮小
isinf(double num) num為正無窮返回1、num為負無窮返回-1
atoll(const char *cstring)返回一個long long int
4)YYNSDateFormString:格式化時間string
這個函數適配了Google、Github、Apple、Facebook、Weibo、Twitter的幾種時間的格式,通過一個block,使用不同的回調來實現不同的適配。
其中學到了使用block數組來根據不同的場景,實現不同的回調。
5)YYNSBlockClass:獲得NSBlock類型,再確認屬性類型時使用
6)YYISODateFormatter:從命名可以知道作用
7)YYValueForKeyPath和YYValueForMultiKeys:使用key或者keys從dic中取得value
8)ModelCreateNumberFromProperty:從_YYModelPropertyMeta中得到Number(使用在屬性是number的情況),通過runtime方法objc_msgSend向當前的model發送消息(getter),得到number。
9)ModelSetNumberToProperty:通過_YYModelPropertyMeta設置property的number(使用在屬性是number的情況),同上,給當前model設置數值。
10)ModelSetValueForProperty:從命名可以看出這個是set property的方法,它根據meta中保存的當前property是什么類型來確定使用什么類型來初始化當前property的值
11)ModelSetWithDictionaryFunction:對ModelSetValueForProperty的封裝,更好的通過解析字典的數據到model中,使用CFDictionaryApplyFunction函數來調用,實現解析字典中的每一個key對應的值
12)ModelSetWithPropertyMetaArrayFunction:解析多個key對應一個property meta的情況
13)ModelToJSONObjectRecursive:model轉換為json
3、NSObject、NSArray、NSDictionary的分類
定義接口通過上述的內聯函數實現相應的功能,方便外部調用,通過這一層封裝就可以簡單明了的調用這些方法來實現功能了,具體的使用請看大神@ibireme的使用說明
https://github.com/ibireme/YYModel。
其中在YYClassIvarInfo、YYCLassMethodInfo、YYClassPropertyInfo中都有一個TypeEncoding的屬性,相關的具體內容請查看Type Encoding:官方鏈接:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW5
最后說一下寫在 最前面的宏定義,
#define force_inline __inline__ __attribute__((always_inline))
從字面意思就可以看出來,是強制內聯的意思。
inline關鍵字僅僅是建議編譯器做內聯展開處理,不是強制的。在gcc編譯器中,如果編譯優化設置為O0,即使是inline函數也不會被內聯展開,除非強制內聯。
1、inline
inline主要是用來替換C中的表達式形式的宏定義,因為這樣的宏定義其實類似於一個函數,但是在宏定義中只是做了簡單的符號替換,它不能進行參數有效性的檢查,也不能享受編譯器嚴格嚴查的好處,同時返回值也不能被強制類型轉換等等,這樣使用宏定義就存在一系列的隱患和局限性。所以出現了inline關鍵字。
因此,inline函數也是直接使用的替換(像宏一樣),沒有了調用的開銷,效率比較高。
inline在文件內部調用時,會被內聯展開,但是gcc還是會為inline函數生成一份獨立的匯編碼以供外部文件使用。gcc的inline函數是全局的,文件內是內聯展開,文件外和普通的extern函數一樣。
2、static inline
也是和inline一樣建議編譯器內聯展開,gcc一般不會為static inline函數生成一份獨立的匯編碼,但是當函數本身遞歸:函數的地址被使用(函數指針),也是會不展開的。