ios - JSONModel iOS 和多态性

标签 ios json model-view-controller model jsonmodel

以以下模型为例,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

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

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

使用通用的 GameEventModel 会更好吗?其中包含 type属性(property)和info属性(property)如...

@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 的 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] } ] }

关于ios - JSONModel iOS 和多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22159573/

相关文章:

iphone - layoutSubviews 究竟什么时候被自定义 UITableViewCell 调用?

iphone - 将 iPhone 应用移植到 iPad

javascript - 如何将数据从 json api 传递到 javascript var

python - 在 Python 中更新复杂的 JSON 对象

python - 如何使用 python 将列表中的信息填充到多个 JSON 对象中?

ruby-on-rails - Ruby on Rails 复选框不会在表单提交时更新

jquery - 使用 ASP.NET MVC Jquery Ajax 序列化表单对象和集合

html - 只获取 HTML 正文,没有标签

ios - Swift JSON 表格 View

Javascript MVC - 轻量级?