我們來分析YYClassInfo這個類,一開始,作者寫了3種編碼
typedef NS_OPTIONS(NSUInteger, YYEncodingType) {
//低八位的值:變量的數(shù)據(jù)類型
YYEncodingTypeMask = 0xFF, ///< mask of type value
//未知類型
YYEncodingTypeUnknown = 0, ///< unknown
//變量的數(shù)據(jù)類型
//基礎(chǔ)數(shù)據(jù)類型
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
//1.自定義類型 2.NSObject
YYEncodingTypeObject = 14, ///< id
//Class類型
YYEncodingTypeClass = 15, ///< Class
YYEncodingTypeSEL = 16, ///< SEL
YYEncodingTypeBlock = 17, ///< block
YYEncodingTypePointer = 18, ///< void*
YYEncodingTypeStruct = 19, ///< struct
YYEncodingTypeUnion = 20, ///< union
//字符串
YYEncodingTypeCString = 21, ///< char*
//數(shù)組
YYEncodingTypeCArray = 22, ///< char[10] (for example)
//取得8~16位的值類型:方法類型
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
//取得16~24位的值類型:屬性的附加修飾類型
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
};
這里分別有3個Mask,分別是YYEncodingTypeMask,YYEncodingTypeQualifierMask,YYEncodingTypePropertyMask
這個有什么用呢,我們來看個例子就知道了
typedef NS_OPTIONS(NSUInteger, JJEncodingType) {
JJEncodingTypeMask = 0xFF,
JJEncodingType1 = 1,
JJEncodingType2 = 2,
JJEncodingType3 = 3,
JJEncodingTypeQualifireMask = 0xFF00,
JJEncodingTypeQualifire1 = 1 << 8,
JJEncodingTypeQualifire2 = 1 << 9,
JJEncodingTypeQualifire3 = 1 << 10,
};
NSLog(@"JJEncodingType1 %d JJEncodingTypeQualifire2 %d",(int)JJEncodingType1,(int)JJEncodingTypeQualifire2);
JJEncodingType test = (JJEncodingType1|JJEncodingTypeQualifire2);
NSLog(@"%d",(int) test);
NSLog(@"JJEncodingTypeMask %d, JJEncodingTypeQualifireMask %d",(int)(test&JJEncodingTypeMask), (int)(test&JJEncodingTypeQualifireMask));
打印的結(jié)果
JJEncodingType1 1 JJEncodingTypeQualifire2 512
513
JJEncodingTypeMask 1, JJEncodingTypeQualifireMask 512
這就很明顯了,如果有個屬性分別具有JJEncodingType1和JJEncodingTypeQualifire2 的屬性,我們可以通過Mask取出來,
然后是獲取類型的方法,
//獲取Type的 encode 返回枚舉的YYEncodingType類型
YYEncodingType YYEncodingGetType(const char *typeEncoding) {
//轉(zhuǎn)換const char 為char
char *type = (char *)typeEncoding;
//如果獲取不到type或者type長度<1 則返回未知類型
if (!type) return YYEncodingTypeUnknown;
size_t len = strlen(type);
if (len == 0) return YYEncodingTypeUnknown;
//用qulifier來確定當(dāng)前type的encode
YYEncodingType qualifier = 0;
bool prefix = true;
//判斷method的類型,如果有就type指針+1,判斷下一個字符,如果沒有則跳出循環(huán)
while (prefix) {
switch (*type) {
case 'r': {
qualifier |= YYEncodingTypeQualifierConst;
type++;
} break;
case 'n': {
qualifier |= YYEncodingTypeQualifierIn;
type++;
} break;
case 'N': {
qualifier |= YYEncodingTypeQualifierInout;
type++;
} break;
case 'o': {
qualifier |= YYEncodingTypeQualifierOut;
type++;
} break;
case 'O': {
qualifier |= YYEncodingTypeQualifierBycopy;
type++;
} break;
case 'R': {
qualifier |= YYEncodingTypeQualifierByref;
type++;
} break;
case 'V': {
qualifier |= YYEncodingTypeQualifierOneway;
type++;
} break;
default: { prefix = false; } break;
}
}
//獲取變化后的type長度
len = strlen(type);
//再一次判斷是否為未知類型
if (len == 0) return YYEncodingTypeUnknown | qualifier;
//判斷變量的類型
switch (*type) {
case 'v': return YYEncodingTypeVoid | qualifier;
case 'B': return YYEncodingTypeBool | qualifier;
case 'c': return YYEncodingTypeInt8 | qualifier;
case 'C': return YYEncodingTypeUInt8 | qualifier;
case 's': return YYEncodingTypeInt16 | qualifier;
case 'S': return YYEncodingTypeUInt16 | qualifier;
case 'i': return YYEncodingTypeInt32 | qualifier;
case 'I': return YYEncodingTypeUInt32 | qualifier;
case 'l': return YYEncodingTypeInt32 | qualifier;
case 'L': return YYEncodingTypeUInt32 | qualifier;
case 'q': return YYEncodingTypeInt64 | qualifier;
case 'Q': return YYEncodingTypeUInt64 | qualifier;
case 'f': return YYEncodingTypeFloat | qualifier;
case 'd': return YYEncodingTypeDouble | qualifier;
case 'D': return YYEncodingTypeLongDouble | qualifier;
case '#': return YYEncodingTypeClass | qualifier;
case ':': return YYEncodingTypeSEL | qualifier;
case '*': return YYEncodingTypeCString | qualifier;
case '^': return YYEncodingTypePointer | qualifier;
case '[': return YYEncodingTypeCArray | qualifier;
case '(': return YYEncodingTypeUnion | qualifier;
case '{': return YYEncodingTypeStruct | qualifier;
case '@': {
if (len == 2 && *(type + 1) == '?')
return YYEncodingTypeBlock | qualifier;
else
return YYEncodingTypeObject | qualifier;
}
default: return YYEncodingTypeUnknown | qualifier;
}
}
知道了如何進(jìn)行鍵值編碼,我們繼續(xù)來看YYClassInfo的組成
分別為YYClassIvarInfo,YYClassMethodInfo,YYClassPropertyInfo
@interface YYClassIvarInfo : NSObject
@property (nonatomic, assign, readonly) Ivar ivar; ///< ivar
@property (nonatomic, strong, readonly) NSString *name; ///< 成員變量名
@property (nonatomic, assign, readonly) ptrdiff_t offset; ///< 變量的偏移地址
@property (nonatomic, strong, readonly) NSString *typeEncoding; ///< 變量的編碼類型
@property (nonatomic, assign, readonly) YYEncodingType type; ///< 轉(zhuǎn)成YYType類型
//通過一個ivar填充YYClassIvarInfo
- (instancetype)initWithIvar:(Ivar)ivar;
@end
@implementation YYClassIvarInfo
- (instancetype)initWithIvar:(Ivar)ivar {
//判斷是否為一個合法的ivar
if (!ivar) return nil;
self = [super init];
_ivar = ivar;
//獲取ivar的名稱
const char *name = ivar_getName(ivar);
if (name) { //轉(zhuǎn)化const char 屬性為NSString
_name = [NSString stringWithUTF8String:name];
}
//取得相對偏移量,這樣做可以提高獲取效率
_offset = ivar_getOffset(ivar);
const char *typeEncoding = ivar_getTypeEncoding(ivar);
if (typeEncoding) { //獲取編碼并轉(zhuǎn)為YYType
_typeEncoding = [NSString stringWithUTF8String:typeEncoding];
_type = YYEncodingGetType(typeEncoding);
}
return self;
}
@end
@interface YYClassMethodInfo : NSObject
@property (nonatomic, assign, readonly) Method method; ///< 方法
@property (nonatomic, strong, readonly) NSString *name; ///< ?方法名
@property (nonatomic, assign, readonly) SEL sel; ///< sel:方法選擇器
@property (nonatomic, assign, readonly) IMP imp; ///< 方法實現(xiàn)
@property (nonatomic, strong, readonly) NSString *typeEncoding; ///< 方法的編碼
@property (nonatomic, strong, readonly) NSString *returnTypeEncoding; ///< 返回值的類型
@property (nullable, nonatomic, strong, readonly) NSArray<NSString *> *argumentTypeEncodings; ///< 方法參數(shù)的編碼
//通過一個方法填充YYClassMethodInfo
- (instancetype)initWithMethod:(Method)method;
@end
屬性的描述信息
@interface YYClassPropertyInfo : NSObject
@property (nonatomic, assign, readonly) objc_property_t property; ///< property
@property (nonatomic, strong, readonly) NSString *name; ///< 屬性名
@property (nonatomic, assign, readonly) YYEncodingType type; ///< 屬性類型
@property (nonatomic, strong, readonly) NSString *typeEncoding; ///< 屬性編碼
@property (nonatomic, strong, readonly) NSString *ivarName; ///< ?屬性對應(yīng)的ivar名字
@property (nullable, nonatomic, assign, readonly) Class cls; ///< 屬性的class
@property (nullable, nonatomic, strong, readonly) NSArray<NSString *> *protocols; ///< 屬性的協(xié)議簇
@property (nonatomic, assign, readonly) SEL getter; ///< getter (nonnull)
@property (nonatomic, assign, readonly) SEL setter; ///< setter (nonnull)
//用屬性填充YYClassPropertyInfo
- (instancetype)initWithProperty:(objc_property_t)property;
@end
暫時寫到這里....發(fā)現(xiàn)要去惡補(bǔ)c++,所以等有空再更..