/**
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 | 屬性信息 |