Bläddra i källkod

support pseudo generic class with protocol name

ibireme 9 år sedan
förälder
incheckning
6136b54598
4 ändrade filer med 69 tillägg och 9 borttagningar
  1. 12 0
      YYModel/NSObject+YYModel.m
  2. 1 0
      YYModel/YYClassInfo.h
  3. 21 7
      YYModel/YYClassInfo.m
  4. 35 2
      YYModelTests/YYTestModelMapper.m

+ 12 - 0
YYModel/NSObject+YYModel.m

@@ -346,6 +346,18 @@ static force_inline id YYValueForMultiKeys(__unsafe_unretained NSDictionary *dic
 
 @implementation _YYModelPropertyMeta
 + (instancetype)metaWithClassInfo:(YYClassInfo *)classInfo propertyInfo:(YYClassPropertyInfo *)propertyInfo generic:(Class)generic {
+    
+    // support pseudo generic class with protocol name
+    if (!generic && propertyInfo.protocols) {
+        for (NSString *protocol in propertyInfo.protocols) {
+            Class cls = objc_getClass(protocol.UTF8String);
+            if (cls) {
+                generic = cls;
+                break;
+            }
+        }
+    }
+    
     _YYModelPropertyMeta *meta = [self new];
     meta->_name = propertyInfo.name;
     meta->_type = propertyInfo.type;

+ 1 - 0
YYModel/YYClassInfo.h

@@ -128,6 +128,7 @@ YYEncodingType YYEncodingGetType(const char *typeEncoding);
 @property (nonatomic, strong, readonly) NSString *typeEncoding;   ///< property's encoding value
 @property (nonatomic, strong, readonly) NSString *ivarName;       ///< property's ivar name
 @property (nullable, nonatomic, assign, readonly) Class cls;      ///< may be nil
+@property (nullable, nonatomic, strong, readonly) NSArray<NSString *> *protocols; ///< may nil
 @property (nonatomic, assign, readonly) SEL getter;               ///< getter (nonnull)
 @property (nonatomic, assign, readonly) SEL setter;               ///< setter (nonnull)
 

+ 21 - 7
YYModel/YYClassInfo.m

@@ -168,14 +168,28 @@ YYEncodingType YYEncodingGetType(const char *typeEncoding) {
                 if (attrs[i].value) {
                     _typeEncoding = [NSString stringWithUTF8String:attrs[i].value];
                     type = YYEncodingGetType(attrs[i].value);
-                    if ((type & YYEncodingTypeMask) == YYEncodingTypeObject) {
-                        size_t len = strlen(attrs[i].value);
-                        if (len > 3) {
-                            char name[len - 2];
-                            name[len - 3] = '\0';
-                            memcpy(name, attrs[i].value + 2, len - 3);
-                            _cls = objc_getClass(name);
+                    
+                    if ((type & YYEncodingTypeMask) == YYEncodingTypeObject && _typeEncoding.length) {
+                        NSScanner *scanner = [NSScanner scannerWithString:_typeEncoding];
+                        if (![scanner scanString:@"@\"" intoString:NULL]) continue;
+                        
+                        NSString *clsName = nil;
+                        if ([scanner scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString:@"\"<"] intoString:&clsName]) {
+                            if (clsName.length) _cls = objc_getClass(clsName.UTF8String);
                         }
+                        
+                        NSMutableArray *protocols = nil;
+                        while ([scanner scanString:@"<" intoString:NULL]) {
+                            NSString* protocol = nil;
+                            if ([scanner scanUpToString:@">" intoString: &protocol]) {
+                                if (protocol.length) {
+                                    if (!protocols) protocols = [NSMutableArray new];
+                                    [protocols addObject:protocol];
+                                }
+                            }
+                            [scanner scanString:@">" intoString:NULL];
+                        }
+                        _protocols = protocols;
                     }
                 }
             } break;

+ 35 - 2
YYModelTests/YYTestModelMapper.m

@@ -55,6 +55,20 @@
 @end
 
 
+
+
+
+
+@protocol YYTestPropertyMapperModelAuto <NSObject>
+@end
+
+@protocol YYTestPropertyMapperModelCustom <NSObject>
+@end
+
+@protocol YYSimpleProtocol <NSObject>
+@end
+
+
 @interface YYTestPropertyMapperModelContainer : NSObject
 @property (nonatomic, strong) NSArray *array;
 @property (nonatomic, strong) NSMutableArray *mArray;
@@ -62,6 +76,10 @@
 @property (nonatomic, strong) NSMutableDictionary *mDict;
 @property (nonatomic, strong) NSSet *set;
 @property (nonatomic, strong) NSMutableSet *mSet;
+
+@property (nonatomic, strong) NSArray<YYTestPropertyMapperModelAuto> *pArray1;
+@property (nonatomic, strong) NSArray<YYSimpleProtocol,YYTestPropertyMapperModelAuto> *pArray2;
+@property (nonatomic, strong) NSArray<YYSimpleProtocol,YYTestPropertyMapperModelCustom> *pArray3;
 @end
 
 @implementation YYTestPropertyMapperModelContainer
@@ -74,7 +92,10 @@
 + (NSDictionary *)modelCustomPropertyMapper {
     return @{ @"mArray" : @"array",
               @"mDict" : @"dict",
-              @"mSet" : @"set"};
+              @"mSet" : @"set",
+              @"pArray1" : @"array",
+              @"pArray2" : @"array",
+              @"pArray3" : @"array"};
 }
 + (NSDictionary *)modelContainerPropertyGenericClass {
     return @{@"array" : YYTestPropertyMapperModelAuto.class,
@@ -82,7 +103,8 @@
              @"dict" : YYTestPropertyMapperModelAuto.class,
              @"mDict" : YYTestPropertyMapperModelAuto.class,
              @"set" : @"YYTestPropertyMapperModelAuto",
-             @"mSet" : @"YYTestPropertyMapperModelAuto"};
+             @"mSet" : @"YYTestPropertyMapperModelAuto",
+             @"pArray3" : @"YYTestPropertyMapperModelAuto"};
 }
 @end
 
@@ -198,6 +220,17 @@
     XCTAssertTrue([((YYTestPropertyMapperModelAuto *)model.array[2]).count isEqual:@12]);
     XCTAssertTrue([model.mArray isKindOfClass:[NSMutableArray class]]);
     
+    XCTAssertTrue(model.pArray1.count == 3);
+    XCTAssertTrue([((YYTestPropertyMapperModelAuto *)model.pArray1[0]).name isEqualToString:@"Apple"]);
+    XCTAssertTrue([((YYTestPropertyMapperModelAuto *)model.pArray1[0]).count isEqual:@10]);
+    XCTAssertTrue(model.pArray2.count == 3);
+    XCTAssertTrue([((YYTestPropertyMapperModelAuto *)model.pArray2[0]).name isEqualToString:@"Apple"]);
+    XCTAssertTrue([((YYTestPropertyMapperModelAuto *)model.pArray2[0]).count isEqual:@10]);
+    XCTAssertTrue(model.pArray3.count == 3);
+    XCTAssertTrue([((YYTestPropertyMapperModelAuto *)model.pArray3[0]).name isEqualToString:@"Apple"]);
+    XCTAssertTrue([((YYTestPropertyMapperModelAuto *)model.pArray3[0]).count isEqual:@10]);
+    
+    
     jsonObject = [model yy_modelToJSONObject];
     XCTAssertTrue([jsonObject[@"array"] isKindOfClass:[NSArray class]]);