/**
Type encoding's type. */ 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 }; 复制代码
Type Encodings 官方文档:@encode
是一个编译器指令,返回类型内部表示的字符串 ,例:@encode(int)
= i ,其做用就是能够加快运行时库的消息分发。html
Code | Meaning |
---|---|
c | char |
i | int |
s | short |
l | long |
q | long long |
C | unsigned char |
I | unsigned int |
S | unsigned short |
L | unsigned long |
Q | unsigned long long |
f | float |
d | double |
B | C++ bool or a C99 _Bool |
v | void |
* | character string (char *) |
@ | object (whether statically typed or typed id) |
# | class object (Class) |
: | method selector (SEL) |
[array type] | array |
{name=type...} | structure |
(name=type...) | union |
bnum | bit field of num bits |
^type | pointer to type |
? | unknown type (among other things, this code is used for function pointers) |
^
。char *
拥有本身的编码 *
long double
类型,传入long double
会和double
同样返回d
。。BOOL
是 c
,而不是 i
。缘由是 Objective-C 设计之初每一个 bit 都比今天的要值钱, char
比 int
占位小。BOOL
更确切地说是 signed char
(即便设置了 -funsigned-char
参数),以在不一样编译器之间保持一致,由于 char
能够是 signed
或者 unsigned
。NSObject
会返回 {NSObject=#}
。可是传入 [NSObject class]
产生一个名为 NSObject
的只有一个类字段的结构体,就是实例变量 isa
。全部的 NSObject
实例都用它来表示本身的类型。[12^f]
。typedef struct example { id anObject; char *aString; int anInt; } Example;
{Example=@*i}
。^{Example=@*i}
YYEncodingType YYEncodingGetType(const char *typeEncoding);
复制代码
typeEncoding
转为 YYEncodingType
的方法,方便使用。数组
/**
Instance variable information.
*/
@interface YYClassIvarInfo : NSObject
@property (nonatomic, assign, readonly) Ivar ivar; ///< ivar opaque struct
@property (nonatomic, strong, readonly) NSString *name; ///< Ivar's name @property (nonatomic, assign, readonly) ptrdiff_t offset; ///< Ivar's offset
@property (nonatomic, strong, readonly) NSString *typeEncoding; ///< Ivar's type encoding @property (nonatomic, assign, readonly) YYEncodingType type; ///< Ivar's type
/**
Creates and returns an ivar info object.
@param ivar ivar opaque struct
@return A new object, or nil if an error occurs.
*/
- (instancetype)initWithIvar:(Ivar)ivar;
@end
复制代码
YYClassIvarInfo
是 objc_ivar
结构体的封装缓存
先科普一下objc_ivar
,这是 Runtime
中表示变量的结构体bash
struct objc_ivar {
char * _Nullable ivar_name OBJC2_UNAVAILABLE; // 名称
char * _Nullable ivar_type OBJC2_UNAVAILABLE; // 类型
int ivar_offset OBJC2_UNAVAILABLE; // 偏移字节
#ifdef __LP64__ // 若是已定义 __LP64__ 则表示正在构建 64 位目标
int space OBJC2_UNAVAILABLE; // 变量空间
#endif
}
复制代码
说明以下:app
属性名 | 说明 |
---|---|
ivar | 变量,对应 objc_ivar |
name | 变量名称,对应 ivar_name |
offset | 变量偏移字节,对应 ivar_offset |
typeEncoding | 变量类型编码,经过 ivar_getTypeEncoding 函数获得 |
type(扩展) | 变量类型,经过 YYEncodingGetType 方法从类型编码中获得 |
/**
Method information.
*/
@interface YYClassMethodInfo : NSObject
@property (nonatomic, assign, readonly) Method method; ///< method opaque struct
@property (nonatomic, strong, readonly) NSString *name; ///< method name
@property (nonatomic, assign, readonly) SEL sel; ///< method's selector @property (nonatomic, assign, readonly) IMP imp; ///< method's implementation
@property (nonatomic, strong, readonly) NSString *typeEncoding; ///< method's parameter and return types @property (nonatomic, strong, readonly) NSString *returnTypeEncoding; ///< return value's type
@property (nullable, nonatomic, strong, readonly) NSArray<NSString *> *argumentTypeEncodings; ///< array of arguments' type /** Creates and returns a method info object. @param method method opaque struct @return A new object, or nil if an error occurs. */ - (instancetype)initWithMethod:(Method)method; @end 复制代码
YYClassMethodInfo
是 objc_method
结构体的封装ide
先科普一下 objc_method
,这是 Runtime
中定义方法的结构体函数
struct objc_method {
SEL method_name; // 方法名
char *method_types; // 方法类型
IMP method_imp; // 函数指针(方法实现)
}
复制代码
神奇的是 method_name
类型是SEL~
SEL是方法选择器 selector
的简。运行时,发消息就是发送SEL,根据SEL找到地址,最后调用方法。ui
具体怎么找的不用关注,猜想有多是方法和方法名字符串的映射~this
说明以下:编码
属性名 | 说明 |
---|---|
method | 方法 |
name | 方法名,对应method_name |
sel | 方法选择器 |
imp | 函数指针(方法实现),对应 method_imp |
typeEncoding | 方法类型编码,对应 method_types |
returnTypeEncoding | 返回值类型编码 |
argumentTypeEncodings | 参数类型编码,数组 |
/**
Property information.
*/
@interface YYClassPropertyInfo : NSObject
@property (nonatomic, assign, readonly) objc_property_t property; ///< property's opaque struct @property (nonatomic, strong, readonly) NSString *name; ///< property's name
@property (nonatomic, assign, readonly) YYEncodingType type; ///< property's type @property (nonatomic, strong, readonly) NSString *typeEncoding; ///< property's encoding value
@property (nonatomic, strong, readonly) NSString *ivarName; ///< property's ivar name @property (nullable, nonatomic, assign, readonly) Class cls; ///< may be nil @property (nullable, nonatomic, strong, readonly) NSArray<NSString *> *protocols; ///< may nil @property (nonatomic, assign, readonly) SEL getter; ///< getter (nonnull) @property (nonatomic, assign, readonly) SEL setter; ///< setter (nonnull) /** Creates and returns a property info object. @param property property opaque struct @return A new object, or nil if an error occurs. */ - (instancetype)initWithProperty:(objc_property_t)property; @end 复制代码
YYClassPropertyInfo
是做者对 property_t
的封装,
先科普一下 property_t
,这是 Runtime
中表示属性的结构体。
struct property_t {
const char *name; // 名称
const char *attributes; // 修饰
};
复制代码
说明以下:
属性名 | 说明 |
---|---|
property | property_t 结构体 |
name | 属性名,对应 name |
type(扩展) | 属性类型 |
typeEncoding(扩展) | 属性类型编码 |
ivarName(扩展) | 变量名称 |
protocols(扩展) | 协议 |
getter(扩展) | getter 方法选择器 |
setter(扩展) | setter 方法选择器 |
/**
Class information for a class.
*/
@interface YYClassInfo : NSObject
@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
/**
If the class is changed (for example: you add a method to this class with
'class_addMethod()'), you should call this method to refresh the class info cache.
After called this method, `needUpdate` will returns `YES`, and you should call
'classInfoWithClass' or 'classInfoWithClassName' to get the updated class info.
*/
- (void)setNeedUpdate;
/**
If this method returns `YES`, you should stop using this instance and call
`classInfoWithClass` or `classInfoWithClassName` to get the updated class info.
@return Whether this class info need update.
*/
- (BOOL)needUpdate;
/**
Get the class info of a specified Class.
@discussion This method will cache the class info and super-class info
at the first access to the Class. This method is thread-safe.
@param cls A class.
@return A class info, or nil if an error occurs.
*/
+ (nullable instancetype)classInfoWithClass:(Class)cls;
/**
Get the class info of a specified Class.
@discussion This method will cache the class info and super-class info
at the first access to the Class. This method is thread-safe.
@param className A class name.
@return A class info, or nil if an error occurs.
*/
+ (nullable instancetype)classInfoWithClassName:(NSString *)className;
复制代码
YYClassInfo
是做者对 objc_class
的封装,
先科普一下 objc_class
,这是 Runtime
中表示类的结构体。
typedef struct objc_class *Class;
// runtime.h
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY; // isa 指针
#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;
复制代码
说明以下:
属性名 | 说明 |
---|---|
cls | 类 |
superCls | 父类 |
metaCls | 元类 |
isMeta | 自身是否元类 |
name | 类名 |
superClassInfo | 父类的信息 |
ivarInfos | 变量信息 |
methodInfos | 方法信息 |
propertyInfos | 属性信息 |