YYModel源碼閱讀(2)

我們來分析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++,所以等有空再更..

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,054評論 0 9
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,034評論 25 709
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數(shù)據(jù)革命閱讀 13,235評論 2 33
  • 簡介 YYModel 是YY大神寫的 JSON 轉(zhuǎn)模型的庫,其具有高性能,自動類型轉(zhuǎn)換,類型安全,無侵入性,輕量等...
    MaZengyi閱讀 1,177評論 0 1

友情鏈接更多精彩內(nèi)容