以以下模型为例,在JSONModel中处理多态的最佳实践是什么?

@interface GameModel : JSONModel
@property (nonatomic, assign) long id;
@property (nonatomic, assign) NSArray<GameEventModel> *events;
/*
  ...
*/
@end

@interface GameEventModel : JSONModel
@property (nonatomic, assign) long long timestamp;
/*
  ...
*/
@end

@interface GameTouchEventModel : GameEventModel
@property (nonatomic, assign) CGPoint point;
/*
  ...
*/
@end

使用{id:1, events:[{point:{x:1, y:1}, timestamp:...}]}的JSON字符串启动GameModel时

JSONModel将使用GameEventModel并忽略point属性。

最好使用包含GameEventModel属性和type属性的通用info,例如...
@interface GameTouchEventModel : GameEventModel
@property (nonatomic, strong) NSString *type;
@property (nonatomic, strong) NSDictionary *info;
@end

因此,该模型可以接受JSON作为{id:1, events:[{ type:"GameTouchEventModel", info:{ point:{x:1, y:1}, timestamp:... } }]}
这种方法的问题是更难阅读代码,并且没有其他编译器警告/错误。

有没有办法在JSONModel中使用多态模型?

最佳答案

我们通过对JSONModel.m进行了2个较小的改动解决了这一问题,引入了一个新的特殊JSON属性__subclass,该属性由JSONModel解析器获取,并将该值用作对象类型。 __subclass必须是保留关键字(因此,没有模型可以将__subclass用作属性名称)。
JSONModel.m的变更

// ...
-(id)initWithDictionary:(NSDictionary*)dict error:(NSError**)err
{
      // ...
      if ([self __isJSONModelSubClass:property.type]) {

            //initialize the property's model, store it
            JSONModelError* initErr = nil;

            -- id value = [[property.type alloc] initWithDictionary: jsonValue error:&initErr];

            ++ id value;
            ++ if([jsonValue valueForKey:@"subclass"] != NULL)
            ++ {
            ++       Class jsonSubclass = NSClassFromString([d valueForKey:@"subclass"]);
            ++       if(jsonSubclass)
            ++             obj = [[jsonSubclass alloc] initWithDictionary:d error:&initErr];
            ++ }
            ++ else
            ++     value = [[property.type alloc] initWithDictionary: jsonValue error:&initErr];
       //...
//...
+(NSMutableArray*)arrayOfModelsFromDictionaries:(NSArray*)array error:(NSError**)err
{
      // ...
      for (NSDictionary* d in array) {
           JSONModelError* initErr = nil;

           -- id obj = [[self alloc] initWithDictionary:d error:&initErr];

           ++ id obj;
           ++ if([d valueForKey:@"subclass"] != NULL)
           ++ {
           ++       Class jsonSubclass = NSClassFromString([d valueForKey:@"subclass"]);
           ++       if(jsonSubclass)
           ++             obj = [[jsonSubclass alloc] initWithDictionary:d error:&initErr];
           ++ }
           ++ else
           ++      obj = [[self alloc] initWithDictionary:d error:&initErr];
       // ...
 // ...

注意:如果_subclass'ed JSON模型类不存在,则模型将回退到 super class 。

然后,它将与以下模型一起使用
@interface GameModel : JSONModel
@property (nonatomic, assign) long id;
@property (nonatomic, assign) NSArray<GameEventModel> *events;
@end

@protocol GameEventModel
@end

@interface GameEventModel : JSONModel
@property (nonatomic, assign) long long timestamp;
@end

@interface GameTouchEventModel : GameEventModel
@property (nonatomic, strong) NSArray *point;
@end

传递JSON字符串{id:1, events:[ { __subclass:'GameTouchEventModel', timestamp:1, point: [0,0] } ] }

07-26 02:29