YYModel源码笔记

Posted by DragonLi on May 9, 2017

YYModel源码笔记

###2015年底,YYKit业界评价十分高,那时候虽然也从事开发一阵了,有心研读源码,可是公司业务忙,自己水平也很low,直到现在再看,发现还是感觉自己low

正文

相比较其他框架(Mantle,jsonModel,MJExtension)应该是文件最少的

  • YYClassInfo 是对于Class进行了封装,进行封装增加描述

    • YYClassIvarInfo
    • YYClassMethodInfo
    • YYClassPropertyInfo
  • YYModel

    • YYModelMeta—>YYClassInfo
    • YYModelPropertyMeta—> YYClassProperty
  • Xcode6.3新特性记录

    • typedef定义的类型的nullability特性通常依赖于上下文,即使是在Audited Regions中,也不能假定它为nonnull。
    • 复杂的指针类型(如id )必须显示去指定是non null还是nullable。例如,指定一个指向nullable对象的nonnulla指针,可以使用”__nullable id __nonnull”。
    • 我们经常使用的NSError *通常是被假定为一个指向nullable NSError对象的nullable指针。
苹果在Xcode 6.3引入了一个Objective-C的新特性:nullability annotations。这一新特性的核心是两个新的类型注释: __nullable 和 __nonnull 。从字面上我们可以猜到,__nullable表示对象可以是NULL或nil,而__nonnull表示对象不应该为空。当我们不遵循这一规则时,编译器就会给出警告。

如果需要每个属性或每个方法都去指定nonnull和nullable,是一件非常繁琐的事。苹果为了减轻我们的工作量,专门提供了两个宏:NS_ASSUME_NONNULL_BEGIN, NS_ASSUME_NONNULL_END。在这两个宏之间的代码,所有简单指针对象都被假定为nonnull,因此我们只需要去指定那些nullable的指针。
NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END

  • Type Encodings: 类型编码 (YYEncodingType)
    • apple ocrtTypeEncodings doc
    • 苹果对每一个变量的类型进行了编码,对方法的类型也进行了编码,于是我们获取到变量的attributes时,就是经过编译器编码后得到的属性。

LFL = "T@\"LFL\",&,N,V_dragopnLi";
T@"LFL" 就是指这个变量是LFL类型,
&代表的是retain的在ARC状态下也就是strong类型
N表示的是是nonatomic的
V_dragopnLi表示这个变量的名字是dragopnLi

  • YY的ENUM TYPE
    • 变量的数据类型
    • method的attributes
    • 变量的attributes
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      自定义类型 2.NSObject
    YYEncodingTypeClass      = 15, ///< Class  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)  数组
    
    // 取得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
    };
1. 定义三个Mask了,直接可以通过枚举值&对应的mask找到它对应的部分是哪个值,区分值
  • objc2.0中对于ivar,method,property的源码,runtime会为每一个class准备一张virtual table表,表格里以字符串当key,每个key会对应到C function的指针位置。在runtime里,将C function 定义为IMP,将key的C字符串定义为SEL,叫做selector type
    • name
    • type
    • offset
struct ivar_t {
    int32_t *offset;
    const char *name;
    const char *type;
    uint32_t alignment_raw;
    uint32_t size;
    uint32_t alignment() {
        if (alignment_raw == ~(uint32_t)0) return 1U << WORD_SHIFT;
        return 1 << alignment_raw;
    }
};

struct property_t {
    const char *name;
    const char *attributes;
};

struct method_t {
    SEL name;
    const char *types;
    IMP imp;

    struct SortBySELAddress :
        public std::binary_function<const method_t&,
                                    const method_t&, bool>
    {
        bool operator() (const method_t& lhs,
                         const method_t& rhs)
        { return lhs.name < rhs.name; }
    };
};