被误解的 objc_class
网上绝大多数的博客讲 objc_class
的定义,基本上都使用了下面的代码一 来讲解,与 objc4 源码 objc-runtime-new.h
中关于 objc_class
中的定义完全不一样,我认真地去探究了一下,发现这个世界上实属雷同的事件还是蛮多的,老实做事做学问的人少的可怜!
本文的所涉及到的 objc4 源码,截止到写本文最新的是 objc4-750
这个版本。
代码一:简洁版也称坑货版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 struct objc_class { Class _Nonnull isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class _Nullable super_class OBJC2_UNAVAILABLE; const char * _Nonnull name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE; struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE; struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE; struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE;
在上面的代码中 OBJC2_UNAVAILABLE
看起来让人觉得有点奇怪,从字面意思上可以理解为在OC2.0版本不可用了,还有一个 OBJC_ISA_AVAILABILITY
是在表示 Objective-C 都可以使用吗?
在 objc-api.h
中有关于这两个宏的定义,如下:
代码二:关键宏定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #if !defined(OBJC_ISA_AVAILABILITY) # if __OBJC2__ # define OBJC_ISA_AVAILABILITY __attribute__((deprecated)) # else # define OBJC_ISA_AVAILABILITY # endif #endif #if !defined(OBJC2_UNAVAILABLE) # if __OBJC2__ # define OBJC2_UNAVAILABLE UNAVAILABLE_ATTRIBUTE # else # 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中已经不可用了,将来会被移除的。
我们不妨来摘录完整的代码,如下:
代码三:完整版也称整明白版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #if !OBJC_TYPES_DEFINED typedef struct objc_method *Method;typedef struct objc_ivar *Ivar;typedef struct objc_category *Category;typedef struct objc_property *objc_property_t;struct objc_class { Class _Nonnull isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class _Nullable super_class OBJC2_UNAVAILABLE; const char * _Nonnull name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE; struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE; struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE; struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE; #endif
这里居然还有个宏 OBJC_TYPES_DEFINED
,看一下其在 objc-private.h
中的定义,如下:
1 #define OBJC_TYPES_DEFINED 1
那么 #if !OBJC_TYPES_DEFINED
已经限制了其到 #endif
中间的代码都是无效的,所以关于代码一 处的代码其实已经没有实际意义了,网上的朋友们请不要拿这段代码再 骗人
了。
源码 objc-runtime-new.h
中关于 objc_class
中的定义代码如下:
代码四:正解版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 struct objc_class : objc_object { Class superclass; cache_t cache; class_data_bits_t bits; } struct objc_object {private: isa_t isa; } union isa_t { isa_t() { } isa_t(uintptr_t value) : bits(value) { } Class cls; uintptr_t bits; #if defined(ISA_BITFIELD) struct { ISA_BITFIELD; }; #endif };
无论是学知识还是做知识,老实认真应该是最基本的要求,千万不要以讹传讹,误人子弟!
只要你想做,总会有办法的~