被誤解的 objc_class
網上絕大多數的部落格講 objc_class
的定義,基本上都使用了下面的 程式碼一 來講解,與 objc4 原始碼 objc-runtime-new.h
中關於 objc_class
中的定義完全不一樣,我認真地去探究了一下,發現這個世界上實屬雷同的事件還是蠻多的,老實做事做學問的缺少的可憐!
本文的所涉及到的 objc4 原始碼,截止到寫本文最新的是 objc4-750
這個版本。
程式碼一:簡潔版也稱坑貨版
struct objc_class { Class _Nonnull isaOBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class _Nullable super_classOBJC2_UNAVAILABLE; const char * _Nonnull nameOBJC2_UNAVAILABLE; long versionOBJC2_UNAVAILABLE; long infoOBJC2_UNAVAILABLE; long instance_sizeOBJC2_UNAVAILABLE; struct objc_ivar_list * _Nullable ivarsOBJC2_UNAVAILABLE; struct objc_method_list * _Nullable * _Nullable methodListsOBJC2_UNAVAILABLE; struct objc_cache * _Nonnull cacheOBJC2_UNAVAILABLE; struct objc_protocol_list * _Nullable protocolsOBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE; /* Use `Class` instead of `struct objc_class *` */
在上面的程式碼中 OBJC2_UNAVAILABLE
看起來讓人覺得有點奇怪,從字面意思上可以理解為在OC2.0版本不可用了,還有一個 OBJC_ISA_AVAILABILITY
是在表示 Objective-C 都可以使用嗎?
在 objc-api.h
中有關於這兩個巨集的定義,如下:
程式碼二:關鍵巨集定義
/* OBJC_ISA_AVAILABILITY: `isa` will be deprecated or unavailable * in the future */ #if !defined(OBJC_ISA_AVAILABILITY) # if __OBJC2__ # define OBJC_ISA_AVAILABILITY __attribute__((deprecated)) # else # define OBJC_ISA_AVAILABILITY /* still available */ # endif #endif /* OBJC2_UNAVAILABLE: unavailable in objc 2.0, deprecated in Leopard */ #if !defined(OBJC2_UNAVAILABLE) # if __OBJC2__ # define OBJC2_UNAVAILABLE UNAVAILABLE_ATTRIBUTE # else /* plain C code also falls here, but this is close enough */ # define OBJC2_UNAVAILABLE \ __OSX_DEPRECATED(10.5, 10.5, "not available in __OBJC2__") \ __IOS_DEPRECATED(2.0, 2.0, "not available in __OBJC2__")\ __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE # endif #endif
從定義來看, OBJC_ISA_AVAILABILITY
在OC2.0版本中標示已經過時了, OBJC2_UNAVAILABLE
標示在OC2.0中已經不可用了,將來會被移除的。
我們不妨來摘錄完整的程式碼,如下:
程式碼三:完整版也稱整明白版
#if !OBJC_TYPES_DEFINED /// An opaque type that represents a method in a class definition. typedef struct objc_method *Method; /// An opaque type that represents an instance variable. typedef struct objc_ivar *Ivar; /// An opaque type that represents a category. typedef struct objc_category *Category; /// An opaque type that represents an Objective-C declared property. typedef struct objc_property *objc_property_t; struct objc_class { Class _Nonnull isaOBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class _Nullable super_classOBJC2_UNAVAILABLE; const char * _Nonnull nameOBJC2_UNAVAILABLE; long versionOBJC2_UNAVAILABLE; long infoOBJC2_UNAVAILABLE; long instance_sizeOBJC2_UNAVAILABLE; struct objc_ivar_list * _Nullable ivarsOBJC2_UNAVAILABLE; struct objc_method_list * _Nullable * _Nullable methodListsOBJC2_UNAVAILABLE; struct objc_cache * _Nonnull cacheOBJC2_UNAVAILABLE; struct objc_protocol_list * _Nullable protocolsOBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE; /* Use `Class` instead of `struct objc_class *` */ #endif
這裡居然還有個巨集 OBJC_TYPES_DEFINED
,看一下其在 objc-private.h
中的定義,如下:
#define OBJC_TYPES_DEFINED 1
那麼 #if !OBJC_TYPES_DEFINED
已經限制了其到 #endif
中間的程式碼都是無效的,所以關於 程式碼一 處的程式碼其實已經沒有實際意義了,網上的朋友們請不要拿這段程式碼再 騙人
了。
做知識還是要老實一點,不要以訛傳訛!
掃碼關注,期待與你的交流~