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; }
};
};