YYModel源碼解析(二)YYClassInfo類

1 . NS_ASSUME_NONNULL_BEGIN

    #define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
    #define NS_ASSUME_NONNULL_END   _Pragma("clang assume_nonnull end")

在YYClassInfo.h的最開始便可以看到這個宏,和NS_ASSUME_NONNULL_BEGIN匹配使用的是NS_ASSUME_NONNULL_END,在這兩個宏之間區(qū)域的代碼的指針都可以認為是nonnull的,如果有需要申明為nullable的話,只需要去單獨申明nullable的指針便可以了。

不過,為了安全起見,蘋果還制定了幾條規(guī)則:

typedef定義的類型的nullability特性通常依賴于上下文,即使是在Audited Regions中,也不能假定它為nonnull。
復(fù)雜的指針類型(如id *)必須顯示去指定是nonnull還是nullable。例如,指定一個指向nullable對象的nonnull指針,可以使用”__nullable id * __nonnull”。
我們經(jīng)常使用的NSError **通常是被假定為一個指向nullable NSError對象的nullable指針。

2 . YYEncodingType
接下來可以看到作者自定義的一大串枚舉

typedef NS_OPTIONS(NSUInteger, YYEncodingType) {
  YYEncodingTypeMask       = 0xFF, ///< mask of type value
  YYEncodingTypeUnknown    = 0, ///< unknown
  YYEncodingTypeVoid       = 1, ///< void
  YYEncodingTypeBool       = 2, ///< bool
  YYEncodingTypeInt8       = 3, ///< char / BOOL
  YYEncodingTypeUInt8      = 4, ///< unsigned char
  YYEncodingTypeInt16      = 5, ///< short
  YYEncodingTypeUInt16     = 6, ///< unsigned short
  YYEncodingTypeInt32      = 7, ///< int
  YYEncodingTypeUInt32     = 8, ///< unsigned int
  YYEncodingTypeInt64      = 9, ///< long long
  YYEncodingTypeUInt64     = 10, ///< unsigned long long
  YYEncodingTypeFloat      = 11, ///< float
  YYEncodingTypeDouble     = 12, ///< double
  YYEncodingTypeLongDouble = 13, ///< long double
  YYEncodingTypeObject     = 14, ///< id
  YYEncodingTypeClass      = 15, ///< Class
  YYEncodingTypeSEL        = 16, ///< SEL
  YYEncodingTypeBlock      = 17, ///< block
  YYEncodingTypePointer    = 18, ///< void*
  YYEncodingTypeStruct     = 19, ///< struct
  YYEncodingTypeUnion      = 20, ///< union
  YYEncodingTypeCString    = 21, ///< char*
  YYEncodingTypeCArray     = 22, ///< char[10] (for example)

  YYEncodingTypeQualifierMask   = 0xFF00,   ///< mask of qualifier
  YYEncodingTypeQualifierConst  = 1 << 8,  ///< const
  YYEncodingTypeQualifierIn     = 1 << 9,  ///< in
  YYEncodingTypeQualifierInout  = 1 << 10, ///< inout
  YYEncodingTypeQualifierOut    = 1 << 11, ///< out
  YYEncodingTypeQualifierBycopy = 1 << 12, ///< bycopy
  YYEncodingTypeQualifierByref  = 1 << 13, ///< byref
  YYEncodingTypeQualifierOneway = 1 << 14, ///< oneway

  YYEncodingTypePropertyMask         = 0xFF0000, ///< mask of property
  YYEncodingTypePropertyReadonly     = 1 << 16, ///< readonly
  YYEncodingTypePropertyCopy         = 1 << 17, ///< copy
  YYEncodingTypePropertyRetain       = 1 << 18, ///< retain
  YYEncodingTypePropertyNonatomic    = 1 << 19, ///< nonatomic
  YYEncodingTypePropertyWeak         = 1 << 20, ///< weak
  YYEncodingTypePropertyCustomGetter = 1 << 21, ///< getter=
  YYEncodingTypePropertyCustomSetter = 1 << 22, ///< setter=
  YYEncodingTypePropertyDynamic      = 1 << 23, ///< @dynamic
};

基本把屬性本身類型和修飾類型,及方法返回類型都進行了枚舉,然后又通過:

YYEncodingType YYEncodingGetType(const char *typeEncoding);

把編譯器編碼的 Type Encodings 在運行時翻譯為定義好的枚舉類型,運作在YYModel體系中。
這里關(guān)于Type Encodings的資料可參考:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html

3 . YYClassInfo類
YYClassInfo 類,其實很簡單,簡單說就是把 Class(struct objc_class *) 封裝成了類并且做了一部分擴展。
對比一下 struct objc_class 和 YYClassInfo的屬性定義部分:

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

YYClassInfo:

@property (nonatomic, assign, readonly) Class cls; ///< class object
@property (nullable, nonatomic, assign, readonly) Class superCls; ///< super class object
@property (nullable, nonatomic, assign, readonly) Class metaCls;  ///< class's meta class object
@property (nonatomic, readonly) BOOL isMeta; ///< whether this class is meta class
@property (nonatomic, strong, readonly) NSString *name; ///< class name
@property (nullable, nonatomic, strong, readonly) YYClassInfo *superClassInfo; ///< super class's class info
@property (nullable, nonatomic, strong, readonly) NSDictionary<NSString *, YYClassIvarInfo *> *ivarInfos; ///< ivars
@property (nullable, nonatomic, strong, readonly) NSDictionary<NSString *, YYClassMethodInfo *> *methodInfos; ///< methods
@property (nullable, nonatomic, strong, readonly) NSDictionary<NSString *, YYClassPropertyInfo *> *propertyInfos; ///< properties

可以看出,相對于 struct objc_class ,YYClassInfo中多了對元類相關(guān)的一些屬性,然后少了幾個沒什么大用的描述性屬性,別的都是一一對應(yīng)的。
然后 YYClassIvarInfo 、YYClassMethodInfo、YYClassPropertyInfo 其實也分別對應(yīng)封裝的 struct objc_ivar 、struct objc_method、 struct objc_property。

然后看一下YYClassInfo的方法:
+ (nullable instancetype)classInfoWithClass:(Class)cls;
+ (nullable instancetype)classInfoWithClassName:(NSString *)className;
沒啥好說的,根據(jù)傳入的參數(shù)獲取生成到的對應(yīng)YYClassInfo對象。

更新方法:
- (void)setNeedUpdate;
- (BOOL)needUpdate;
如果你的類有了一些改變,譬如用 'class_addMethod()' 之類的函數(shù)動態(tài)添加了方法,那么就要手動調(diào)用一下setNeedUpdate,來通知更新對應(yīng)YYClassInfo緩存,之后needUpdate會返回YES, 這種情況下就需要重新用 'classInfoWithClass' 或者 'classInfoWithClassName' 更新信息。

4 . 別的

(1). 在定義 YYClassIvarInfo 中的 offset屬性是用到 ptrdiff_t 類型

ptrdiff_t :ptrdiff_t是C/C++標準庫中定義的一個與機器相關(guān)的數(shù)據(jù)類型。ptrdiff_t類型變量通常用來保存兩個[指針]減法操作的結(jié)果。ptrdiff_t定義在stddef.h(cstddef)這個文件內(nèi)。ptrdiff_t通常被定義為long int類型。ptrdiff_t定義在C99標準中。

ptrdiff_t
標準庫類型(library type)ptrdiff_t 與 size_t 類型一樣,ptrdiff_t 也是一種與機器相關(guān)的類型,在 cstddef 頭文件中定義。size_t 是unsigned 類型,而 ptrdiff_t 則是 signed 整型。

size_t
這兩種類型的差別體現(xiàn)了它們各自的用途:size_t 類型用于指明數(shù)組長度,它必須是一個正數(shù);ptrdiff_t 類型則應(yīng)保證足以存放同一數(shù)組中兩個指針之間的差距,它有可能是負數(shù) 。

----來自 百度百科

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,101評論 0 9
  • Objective-C語言是一門動態(tài)語言,它將很多靜態(tài)語言在編譯和鏈接時期做的事放到了運行時來處理。這種動態(tài)語言的...
    有一種再見叫青春閱讀 682評論 0 3
  • NSObject方法 Cocoa中大多數(shù)對象是繼承自NSObjectl類的子類(唯一例外的是NSProxy類)NS...
    水落斜陽閱讀 486評論 0 1
  • 技術(shù)無極限,從菜鳥開始,從源碼開始。 由于公司目前項目還是用OC寫的項目,沒有升級swift 所以暫時SDWebI...
    充滿活力的早晨閱讀 12,858評論 0 2
  • /呆種子 他不相信時間不可逆轉(zhuǎn)他躲到避世的小屋里發(fā)明起了時光機器人們都認為他瘋了漸漸也遺忘了他 直到有一天平行世界...
    付寒宇閱讀 394評論 0 0

友情鏈接更多精彩內(nèi)容