IOSノート:JSON->ModelのYYYModelソースを1つ削除してノートを読む

8057 ワード

YYModelソース読み取りノート:最初に呼び出す
1. + (instancetype)modelWithJSON:(id)json;
+ (instancetype)modelWithJSON:(id)json {
    //          NSDictionary  ,
    //  NSString,NSData,NSDictionary
    NSDictionary *dic = [self _yy_dictionaryWithJSON:json];
    // jsos->model
    return [self modelWithDictionary:dic];
}


2. + (NSDictionary *)_yy_dictionaryWithJSON:(id)json;
//   NSDictionary
+ (NSDictionary *)_yy_dictionaryWithJSON:(id)json {
    //json     (kCFNull NSNULL   )
    if (!json || json == (id)kCFNull) return nil;
    NSDictionary *dic = nil;
    NSData *jsonData = nil;
    //           
    if ([json isKindOfClass:[NSDictionary class]]) {
        dic = json;
    } else if ([json isKindOfClass:[NSString class]]) { //        ,  NSData  
        jsonData = [(NSString *)json dataUsingEncoding : NSUTF8StringEncoding];
    } else if ([json isKindOfClass:[NSData class]]) {   //   data,    
        jsonData = json;
    }
    if (jsonData) { // data        NSDictionary
        dic = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:NULL];
        if (![dic isKindOfClass:[NSDictionary class]]) dic = nil;
    }
    return dic;
}

3.- (BOOL)modelSetWithDictionary:(NSDictionary *)dic;
- (BOOL)modelSetWithDictionary:(NSDictionary *)dic {
    if (!dic || dic == (id)kCFNull) return NO;  //     
    if (![dic isKindOfClass:[NSDictionary class]]) return NO;   //     
    
    //    model
    _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:object_getClass(self)];
    //   key->property    
    if (modelMeta->_keyMappedCount == 0) return NO;
    
    //         ,      
    if (modelMeta->_hasCustomWillTransformFromDictionary) {
        dic = [((id)self) modelCustomWillTransformFromDictionary:dic];
        if (![dic isKindOfClass:[NSDictionary class]]) return NO;
    }
    //   
    ModelSetContext context = {0};
    //model    
    context.modelMeta = (__bridge void *)(modelMeta);
    //model  
    context.model = (__bridge void *)(self);
    //model    
    context.dictionary = (__bridge void *)(dic);
    
    //CFDictionaryApplyFunction / CFArrayApplyFunction
    //   dictionary / array                       
    //            
    //  model property         
    if (modelMeta->_keyMappedCount >= CFDictionaryGetCount((CFDictionaryRef)dic)) {
        //   json->model :    @{@"name":@"henry"};
        CFDictionaryApplyFunction((CFDictionaryRef)dic, ModelSetWithDictionaryFunction, &context);
        //      modelCustomPropertyMapper   ,             
        if (modelMeta->_keyPathPropertyMetas) {
            /**
            + (NSDictionary *)modelCustomPropertyMapper {
                return @{@"name"  : @"n",
                         @"page"  : @"p",
                         @"desc"  : @"ext.desc",
                         @"bookID": @[@"id", @"ID", @"book_id"]};
            }
             */
            //          @{@"desc"  : @"ext.desc"}
            CFArrayApplyFunction((CFArrayRef)modelMeta->_keyPathPropertyMetas,
                                 CFRangeMake(0, CFArrayGetCount((CFArrayRef)modelMeta->_keyPathPropertyMetas)),
                                 ModelSetWithPropertyMetaArrayFunction,
                                 &context);
        }
        //          @{@"bookID": @[@"id", @"ID", @"book_id"]}
        if (modelMeta->_multiKeysPropertyMetas) {
            CFArrayApplyFunction((CFArrayRef)modelMeta->_multiKeysPropertyMetas,
                                 CFRangeMake(0, CFArrayGetCount((CFArrayRef)modelMeta->_multiKeysPropertyMetas)),
                                 ModelSetWithPropertyMetaArrayFunction,
                                 &context);
        }
    } else {
        //    property
        CFArrayApplyFunction((CFArrayRef)modelMeta->_allPropertyMetas,
                             CFRangeMake(0, modelMeta->_keyMappedCount),
                             ModelSetWithPropertyMetaArrayFunction,
                             &context);
    }
    //         ,(                  )
    if (modelMeta->_hasCustomTransformFromDictionary) {
        return [((id)self) modelCustomTransformFromDictionary:dic];
    }
    return YES;
}

3.1 [_YYModelMeta metaWithClass:object_getClass(self)]; 初期化方法
/// Returns the cached model class meta
+ (instancetype)metaWithClass:(Class)cls {
    if (!cls) return nil;
    static CFMutableDictionaryRef cache;
    static dispatch_once_t onceToken;
    static dispatch_semaphore_t lock;
    dispatch_once(&onceToken, ^{
        cache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
        //     ,          
        lock = dispatch_semaphore_create(1);
    });
    //       -1
    dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
    _YYModelMeta *meta = CFDictionaryGetValue(cache, (__bridge const void *)(cls));
    //       +1
    dispatch_semaphore_signal(lock);
    if (!meta || meta->_classInfo.needUpdate) {
        meta = [[_YYModelMeta alloc] initWithClass:cls];
        if (meta) {
            dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
            CFDictionarySetValue(cache, (__bridge const void *)(cls), (__bridge const void *)(meta));
            dispatch_semaphore_signal(lock);
        }
    }
    return meta;
}


3.2 ModelSetWithDictionaryFunctionベースのdictionary回転モデル
static void ModelSetWithDictionaryFunction(const void *_key, const void *_value, void *_context) {
    //    context   
    ModelSetContext *context = _context;
    //context model    
    __unsafe_unretained _YYModelMeta *meta = (__bridge _YYModelMeta *)(context->modelMeta);
    //        dictionary
    __unsafe_unretained _YYModelPropertyMeta *propertyMeta = [meta->_mapper objectForKey:(__bridge id)(_key)];
    //context model(   )
    __unsafe_unretained id model = (__bridge id)(context->model);
    while (propertyMeta) {
        //       set  , model(   )   property  
        if (propertyMeta->_setter) {
            ModelSetValueForProperty(model, (__bridge __unsafe_unretained id)_value, propertyMeta);
        }
        //    ,     meta     ,   nil   while  
        propertyMeta = propertyMeta->_next;
    };
}

3.3 ModelSetWithPropertyMetaArrayFunction複雑なモード回転モデル
static void ModelSetWithPropertyMetaArrayFunction(const void *_propertyMeta, void *_context) {
    //    context   
    ModelSetContext *context = _context;
    //     
    __unsafe_unretained NSDictionary *dictionary = (__bridge NSDictionary *)(context->dictionary);
    //    
    __unsafe_unretained _YYModelPropertyMeta *propertyMeta = (__bridge _YYModelPropertyMeta *)(_propertyMeta);
    //      set  ,    ,  crash
    if (!propertyMeta->_setter) return;
    id value = nil;
    
    // @{@"bookID": @[@"id", @"ID", @"book_id"]}          
    if (propertyMeta->_mappedToKeyArray) {
        value = YYValueForMultiKeys(dictionary, propertyMeta->_mappedToKeyArray);
    }
    // @{@"desc"  : @"ext.desc"}          
    else if (propertyMeta->_mappedToKeyPath) {
        value = YYValueForKeyPath(dictionary, propertyMeta->_mappedToKeyPath);
    }
    //        
    else {
        value = [dictionary objectForKey:propertyMeta->_mappedToKey];
    }
    
    //    
    if (value) {
        __unsafe_unretained id model = (__bridge id)(context->model);
        ModelSetValueForProperty(model, value, propertyMeta);
    }
}

3.4 ModelSetValueForProperty
ModelSetValueForProperty
      ,    objc_msgSend  , property  
//          
((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value);