YYModel源代码分析(三)NSObject+YYModel

前言

本文的中文注释代码demo更新在我的github上。

上篇 YYModel源代码分析(二)YYClassInfo
主要分析了YYClassInfo文件。本篇会主要集中在NSObject+YYModel文件上。文章内容会包含一些与JSONModel的比较,想了解JSONModel,可以参考JSONModel源代码解析

主体分层

NSObject+YYModel主要分为以下几个部分:

  • 内部使用的C函数部分
  • @interface _YYModelPropertyMeta : NSObject
  • @interface _YYModelMeta : NSObject
  • @interface NSObject (YYModel) : NSObject
  • @interface NSArray (YYModel) : NSObject
  • @interface NSDictionary (YYModel) : NSObject
  • @protocol YYModel <NSObject>:接口YYModel

由于代码较多,所以会挑重点的部分进行介绍。

NSObject+YYModel源代码

@interface _YYModelPropertyMeta : NSObject

声明
/// A property info in object model.
// model property的进一步分装
@interface _YYModelPropertyMeta : NSObject {
   
    @package
    NSString *_name;             ///< property's name                   //property名
    YYEncodingType _type;        ///< property's type                   //property的encode解析值
    YYEncodingNSType _nsType;    ///< property's Foundation type        //property的foundation类型
    BOOL _isCNumber;             ///< is c number type                  //是不是c语言的数字
    Class _cls;                  ///< property's class, or nil          //property的class
    Class _genericCls;           ///< container's generic class, or nil if threr's no generic class     //property内包含的类class
    SEL _getter;                 ///< getter, or nil if the instances cannot respond        //property getter方法
    SEL _setter;                 ///< setter, or nil if the instances cannot respond        //property setter方法
    BOOL _isKVCCompatible;       ///< YES if it can access with key-value coding            //是否可以使用KVC
    BOOL _isStructAvailableForKeyedArchiver; ///< YES if the struct can encoded with keyed archiver/unarchiver      //是否是struct并且可以archiver/unarchiver
    BOOL _hasCustomClassFromDictionary; ///< class/generic class implements +modelCustomClassForDictionary:     //是否包含本本地的class转换

    /*
     property->key:       _mappedToKey:key     _mappedToKeyPath:nil            _mappedToKeyArray:nil
     property->keyPath:   _mappedToKey:keyPath _mappedToKeyPath:keyPath(array) _mappedToKeyArray:nil
     property->keys:      _mappedToKey:keys[0] _mappedToKeyPath:nil/keyPath    _mappedToKeyArray:keys(array)
     */
    NSString *_mappedToKey;      ///< the key mapped to                                     //property本地的key mapper的key
    NSArray *_mappedToKeyPath;   ///< the key path mapped to (nil if the name is not key path)  //property本地的key mapper的key path列表
    NSArray *_mappedToKeyArray;  ///< the key(NSString) or keyPath(NSArray) array (nil if not mapped to multiple keys) /property本地的key mapper的key列表
    YYClassPropertyInfo *_info;  ///< property's info                                   //property的YYClassPropertyInfo info
    _YYModelPropertyMeta *_next; ///< next meta if there are multiple properties mapped to the same key.      //同个key的多个property的映射next指针
}
@end

其中需要理解一下的包括:
1._hasCustomClassFromDictionary就是判断是否有本地的不同class的映射
如下例子,当dictionary包含不同的值的时候,映射的model类型不同

@implementation YYBaseUser
+ (Class)modelCustomClassForDictionary:(NSDictionary*)dictionary {
    if (dictionary[@"localName"]) {
        return [YYLocalUser class];
    } else if (dictionary[@"remoteName"]) {
        return [YYRemoteUser class];
    }
    return [YYBaseUser class];
}

2.keyMapper相关内容
如下例子,dictionary中不同的key,对应的model的property有一个映射关系
其中对于包含”.”的映射,则是一种多层的映射关系

+ (NSDictionary *)modelCustomPropertyMapper {
    return @{ @"name" : @"n",
              @"count" : @"ext.c",
              @"desc1" : @"ext.d", // mapped to same key path
              @"desc2" : @"ext.d", // mapped to same key path
              @"desc3" : @"ext.d.e",
              @"desc4" : @".ext",
              @"modelID" : @[@"ID", @"Id", @"id", @"ext.id"]};
}

3._YYModelPropertyMeta *_next同一个key的下一个meta解析类型
因为有了key mapper,所以会出现同一个mapper的key值,可能会一对多个model的property值,这边设计了一个_next指针进行链接

4.Class _genericCls包含的类型
如下例子,property会有NSArray\NSDictionary\NSSet类型,内部的类型就通过该参数表示

@interface YYTestCustomClassModel : NSObject
@property (nonatomic, strong) NSArray *users;
@property (nonatomic, strong) NSDictionary *userDict;
@property (nonatomic, strong) NSSet *userSet;
@end

+ (NSDictionary *)modelContainerPropertyGenericClass {
    return @{@"users" : YYBaseUser.class,
             @"userDict" : YYBaseUser.class,
             @"userSet" : YYBaseUser.class};
}
实现
//通过YYClassInfo,YYClassPropertyInfo,Class对象解析成_YYModelPropertyMeta
+ (instancetype)metaWithClassInfo:(YYClassInfo *)classInfo propertyInfo:(YYClassPropertyInfo *)propertyInfo generic:(Class)generic {

    // support pseudo generic class with protocol name
    // 这边也考虑了,某些类型写在protocol中,包含在<>中,和JSONModel一样进行一下protocol的类型判断
    // 比如NSArray<TestObject> xxx
    if (!generic && propertyInfo.protocols) {
        for (NSString *protocol in propertyInfo.protocols) {
            Class cls = objc_getClass(protocol.UTF8String);
            if (cls) {
                generic = cls;
                break;
            }
        }
    }

    //构造_YYModelPropertyMeta对象
    _YYModelPropertyMeta *meta = [self new];
    meta->_name = propertyInfo.name;                //设置名
    meta->_type = propertyInfo.type;                //设置encode type
    meta->_info = propertyInfo;                     //设置YYClassPropertyI
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值