YYModel原理分析

一.结构分析
1.文件构成
YYModel.h、YYClassInfo.h、NSObject+YYModel
2.核心类结构
YYClassInfo 是对于Class进行了封装,进行封装增加描述
YYClassIvarInfo 对 Class的Ivar进行了进行封装增加描述
YYClassMethodInfo 对 Class 的 Method进行封装增加描述
YYClassPropertyInfo 对 Class 的 Property进行了封装描述
YYModel :
YYModelMeta 对YYClassInfo进行封装描述
YYModelPropertyMeta对YYClassProperty进行封装描述

二、常用的方法

类别的实例的isa指针指向其类别,类别的isa指向其元类,而所有类别的元类最终都指向上帝类的元类也就是NSObject的元类。这样形成了一个完美的继承链.
instance->class->metaclass


Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

Person *obj = [Person new];
NSLog(@"instance         :%p", obj);
NSLog(@"class            :%p", object_getClass(obj));
NSLog(@"meta class       :%p", object_getClass(object_getClass(obj)));
NSLog(@"root meta        :%p", object_getClass(object_getClass(object_getClass(obj))));
NSLog(@"root meta's meta :%p", object_getClass(object_getClass(object_getClass(object_getClass(obj)))));
NSLog(@"---------------------------------------------");
NSLog(@"class            :%p", [obj class]);
NSLog(@"meta class       :%p", [[obj class] class]);
NSLog(@"root meta        :%p", [[[obj class] class] class]);
NSLog(@"root meta's meta :%p", [[[[obj class] class] class] class]);

2016-02-02 18:06:11.443 TimerDemo[1718:248402] instance         :0x7fc792530f20
2016-02-02 18:06:11.444 TimerDemo[1718:248402] class            :0x10ae0e178
2016-02-02 18:06:11.444 TimerDemo[1718:248402] meta class       :0x10ae0e150
2016-02-02 18:06:11.444 TimerDemo[1718:248402] root meta        :0x10b66a198
2016-02-02 18:06:11.444 TimerDemo[1718:248402] root meta's meta :0x10b66a198
2016-02-02 18:06:11.444 TimerDemo[1718:248402] ---------------------------------------------
2016-02-02 18:06:11.444 TimerDemo[1718:248402] class            :0x10ae0e178
2016-02-02 18:06:11.444 TimerDemo[1718:248402] meta class       :0x10ae0e178
2016-02-02 18:06:11.444 TimerDemo[1718:248402] root meta        :0x10ae0e178
2016-02-02 18:06:11.444 TimerDemo[1718:248402] root meta's meta :0x10ae0e178

0.objc_
objc_allocateClassPair
objc_registerClassPair

1.class_
class_isMetaClass
class_addMethod

Ivar class_getInstanceVariable ( Class cls, const char *name ):类中指定名称实例成员变量的信息
Ivar class_getClassVariable ( Class cls, const char *name ):类成员变量的信息
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types ): 添加成员变量
class_copyMethodList:获取方法列表 含有getter 和 setter
class_copyPropertyList:获取属性列表
class_copyIvarList ( Class cls, unsigned int *outCount );获取整个成员变量列

2.Method
_sel=method_getName:
sel_getName:
method_getImplementation:
method_getTypeEncoding
method_copyReturnType
method_getNumberOfArguments
method_copyArgumentType

3.objc_property_t
property_getName
property_copyAttributeList

4.Ivar
ivar_getName:
ivar_getOffset:
ivar_getTypeEncoding:

Class newClass = 
    objc_allocateClassPair([NSError class], "RuntimeErrorSubclass", 0); 
class_addMethod(newClass, @selector(report), (IMP)ReportFunction, "v@:"); 
objc_registerClassPair(newClass); 

三.函数分析
1.yy_modelWithJSON:
NSDic、NSData、NSString 都转成NSDic.
NSString->NSData->NSDic

NSData *jsonData= [(NSString *)json dataUsingEncoding : NSUTF8StringEncoding]
 NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:NULL]

2.YYModelMeta metaWithClass
创建一个总的CFMutableDictionaryRef缓存,保存每个model,(Key:Class Value:YYModelMeta)
采用dispatch_semaphore
信号量机制保证线程读取安全
create\wait\signal

a.
Class cls = [self class];
_YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:cls]
meta = [[_YYModelMeta alloc] initWithClass:cls];
YYClassInfo *classInfo = [YYClassInfo classInfoWithClass:cls];
b.读取代理的 blacklist、whitelist
c.获取类型需要映射数组 modelContainerPropertyGenericClass
{ @"rightImage" : [FHWHomeRightImage class] }
{ @"rightImage" : @"FHWHomeRightImage" } //FHWHomeRightImage这个需要转化

d.Create all property metas. 对真正要映射属性进行遍历组装成一个数组
d1.判断是否再黑白名单里面才需要处理
d2.生成_YYModelPropertyMeta。入参 classinfo 、propertyInfo、genericMapper[propertyInfo.name]。 一定要有getter setter。
包括superclass,也要一并生成进来。
d3.无视最基类的属性NSObject/NSProxy
while (curClassInfo && curClassInfo.superCls != nil) { // recursive parse super class, but ignore root class (NSObject/NSProxy)

e.// create mapper
modelCustomPropertyMapper

f.yy_modelSetWithDictionary 最后填充映射函数

f1.modelCustomWillTransformFromDictionary:传入映射前,再次进行修改。
f2.CFArrayApplyFunction:遍历Array数组元素,每一次传入一个函数中进行处理
CFDictionaryApplyFunction:遍历
f3.
f4._hasCustomTransformFromDictionary

propertyMeta->_mappedToKeyArray
propertyMeta->_mappedToKeyPath
_isCNumber:C语言格式的数字 特殊处理
((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value);

3.YYClassInfo classInfoWithClass

创建两个缓存 classCache、metaCache
a.当你向一个对象发送消息,就在那个对象的方法列表中查找那个消息。
b.当你想一个类发送消息,就再那个类的 meta-class 中查找那个消息。
NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];
c.含有一个YYClassInfo *superClassInfo的指针。
d.
NSType
非NSType开头
(modelCustomClassForDictionary:)
4.initWithMethod
NSDic存储 HomeKey:YYClassMethodInfo
Method *methods = class_copyMethodList(cls, &methodCount);
普通变量含有 get set的方法、.cxx_destruct
@"HomeKey" 、@"setHomeKey:"
method_getTypeEncoding : "@16@0:8" 、"v24@0:8@16"
method_copyReturnType :"@" 、"v"
method_copyArgumentType : 2 {"@" 、":"} 、3{"@"、":"、"@"}
cxx_destruct:向父类转发dealloc的调用,实现了自动调用[super dealloc]

5.initWithProperty
NSDic存储 HomeKey:YYClassPropertyInfo
objc_property_t *properties = class_copyPropertyList(cls, &propertyCount);
objc_property_attribute_t *attrs = property_copyAttributeList(property, &attrCount);
attrs里面值:
nsstring {"T","NSString"}、copy {"'C'",""}、nonatomic{"N",""}、HomeKey{"V"、"_HomeKey"}.

如果没有显示指定set 、get ,通过变量名自动生成 getter和setter "HomeKey" "setHomeKey:"。

Class cls :NSString
NSArray *protocols: 协议<>
case '&': YYEncodingTypePropertyRetain;
case 'W' :YYEncodingTypePropertyWeak

YYEncodingGetType: 先判断是否是修饰符 in、out 之类 再判断是否指定类型 NSInterger,如果是"@”,开头,区分object和block.block只有2个长度固定为"@?'"

6.Ivar
Ivar *ivars = class_copyIvarList(cls, &ivarCount);
ivar_getName:"_HomeKey"
ivar_getOffset:8
ivar_getTypeEncoding:"@NSString"
_type:YYEncodingTypeObject

7.muikey和key path

YYModel原理分析_第1张图片
image.png

8.反向转化model 转 object
8.1ModelToJSONObjectRecursive
递归遍历

优先判断是否基础类型,如果是直接返还。如果是判断传进来是数组或者字典。先创建一个空的数组或者字典,再把数组或者字典实体进行转化,再存进这个空的数组或者字典,然后返回。

8.2验证最后的结果
只能是NSArray、NSDictionary

9.特殊备注
9.1.[instancesRespondToSelector与respondsToSelector的区别
instancesRespondToSelector只能写在类名后面(类的静态方法+),respondsToSelector可以写在类名和实例名后面。
9.2.特殊类型 nsdata、nsurl、NSAttributedString、NSNumber、
nstype:接收的类型 NSString得做转化,NSMutableString .stringValue.mutableCopy

((void (*)(id,SEL,id))(void *) objc_msgSend)((id)model,meta->_setter,value);

       YYEncodingTypeNSValue:
       YYEncodingTypeNSNumber:
       YYEncodingTypeNSDecimalNumber:

b.NSDecimalNumber、NSValue直接映射,其他类型先转成NSDecimalNumber再映射。
c.NSDate 接手为NSString 帮你手动转化
d.NSArray
f.NSDictionary
g.NSSet
h.YYEncodingTypeObject\

CFArrayApplyFunction

主要类别

NSObject(YYModel) : 提供一些字典模型互转的方法,将对key/value进行匹配,赋值给Model对应的property
NSArray(YYModel): 为NSArray提供字典转模型的方法
NSDictionary(YYModel):为NSDictionary提供字典转模型方法

在 ARC 条件下,默认声明的对象是 strong 类型的,赋值时有可能会产生 retain/release 调用,如果一个变量在其生命周期内不会被释放,则使用 unsafe_unretained 会节省很大的开销。


YYModel原理分析_第2张图片
123.png

你可能感兴趣的:(YYModel原理分析)