Browse Source

Add custom transform method before the default json to model

Arron 9 years ago
parent
commit
cf41f5e151
3 changed files with 42 additions and 1 deletions
  1. 13 0
      YYModel/NSObject+YYModel.h
  2. 12 1
      YYModel/NSObject+YYModel.m
  3. 17 0
      YYModelTests/YYTestCustomTransform.m

+ 13 - 0
YYModel/NSObject+YYModel.h

@@ -396,6 +396,19 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic;
 
+/**
+ This method's behavior is similar to `- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic;`, but be called before the model transform.
+ 
+ @discussion If the model implements this method, it will be called before
+ `+modelWithJSON:`, `+modelWithDictionary:`, `-modelSetWithJSON:` and `-modelSetWithDictionary:`.
+ If this method returns nil, the transform process will ignore this model.
+ 
+ @param dic  The json/kv dictionary.
+ 
+ @return Returns NSDictionary for change the json/kv dictionary, or nil to ignore this model.
+ */
+- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic;
+
 /**
  If the default model-to-json transform does not fit to your model class, implement
  this method to do additional process. You can also use this method to validate the

+ 12 - 1
YYModel/NSObject+YYModel.m

@@ -419,6 +419,8 @@ static force_inline id YYValueForMultiKeys(__unsafe_unretained NSDictionary *dic
     YYEncodingNSType _nsType;
     
     BOOL _hasCustomTransformFromDictionary;
+    BOOL _hasCustomWillTransformFromDictionary;
+
     BOOL _hasCustomTransformToDictionary;
     BOOL _hasCustomClassFromDictionary;
 }
@@ -561,7 +563,8 @@ static force_inline id YYValueForMultiKeys(__unsafe_unretained NSDictionary *dic
     _hasCustomTransformFromDictionary = ([cls instancesRespondToSelector:@selector(modelCustomTransformFromDictionary:)]);
     _hasCustomTransformToDictionary = ([cls instancesRespondToSelector:@selector(modelCustomTransformToDictionary:)]);
     _hasCustomClassFromDictionary = ([cls respondsToSelector:@selector(modelCustomClassForDictionary:)]);
-    
+    _hasCustomWillTransformFromDictionary = ([cls instancesRespondToSelector:@selector(modelCustomWillTransformFromDictionary:)]);
+
     return self;
 }
 
@@ -1422,13 +1425,21 @@ static NSString *ModelDescription(NSObject *model) {
     if (!dic || dic == (id)kCFNull) return NO;
     if (![dic isKindOfClass:[NSDictionary class]]) return NO;
     
+
     _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:object_getClass(self)];
     if (modelMeta->_keyMappedCount == 0) return NO;
+    
+    if (modelMeta->_hasCustomWillTransformFromDictionary) {
+        dic = [((id<YYModel>)self) modelCustomWillTransformFromDictionary:dic];
+        if (![dic isKindOfClass:[NSDictionary class]]) return NO;
+    }
+    
     ModelSetContext context = {0};
     context.modelMeta = (__bridge void *)(modelMeta);
     context.model = (__bridge void *)(self);
     context.dictionary = (__bridge void *)(dic);
     
+    
     if (modelMeta->_keyMappedCount >= CFDictionaryGetCount((CFDictionaryRef)dic)) {
         CFDictionaryApplyFunction((CFDictionaryRef)dic, ModelSetWithDictionaryFunction, &context);
         if (modelMeta->_keyPathPropertyMetas) {

+ 17 - 0
YYModelTests/YYTestCustomTransform.m

@@ -20,6 +20,18 @@
 
 @implementation YYTestCustomTransformModel
 
+
+-(NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic{
+    if (dic) {
+        NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:dic];
+        if (dict[@"date"]) {
+            dict[@"time"] = dict[@"date"];
+        }
+        return dict;
+    }
+    return dic;
+}
+
 - (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic {
     NSNumber *time = dic[@"time"];
     if ([time isKindOfClass:[NSNumber class]] && time.unsignedLongLongValue != 0) {
@@ -74,6 +86,11 @@
     model.time = nil;
     jsonObject = [model yy_modelToJSONObject];
     XCTAssert(jsonObject == nil);
+    
+    json = @"{\"id\":5472746497,\"content\":\"Hello\",\"date\":1401234567000}";
+    model = [YYTestCustomTransformModel yy_modelWithJSON:json];
+    XCTAssert(model.time != nil);
+    
 }
 
 @end