Skip to content

Custom model class for every element.#616

Open
qdvictory wants to merge 10 commits into
jsonmodel:masterfrom
qdvictory:master
Open

Custom model class for every element.#616
qdvictory wants to merge 10 commits into
jsonmodel:masterfrom
qdvictory:master

Conversation

@qdvictory
Copy link
Copy Markdown

In the same location, if there are multiple models, this method can be used to output the corresponding model.

Such as,
[{ "background": "#ff0000", "foreground": "#0000ff", "typeField": "picture" }, { "body": "#ff0000", "tire": "#0000ff", "typeField": "car" }]

there is a list, it has many types. So you want convert to model, it's very inconvenient.

Now, you can create a super class and subclass like:

@interface MultipleModel : JSONModel
@property (strong, nonatomic) NSString *typeField;
@end

@interface MultiplePicModel : MultipleModel
@property (strong, nonatomic) NSString *background;
@property (strong, nonatomic) NSString *foreground;
@end

@interface MultipleCarModel : MultipleModel
@property (strong, nonatomic) NSString *body;
@property (strong, nonatomic) NSString *tire;
@end

---------------------------------------------
@class MultipleCarModel;
@class MultiplePicModel;

@implementation MultipleModel

+ (Class)classForModel:(NSDictionary *)dict
{
	if ([[dict valueForKey:@"typeField"] isEqualToString:@"picture"]) {
		return [MultiplePicModel class];
	}
	else if ([[dict valueForKey:@"typeField"] isEqualToString:@"car"]) {
		return [MultipleCarModel class];
	}
	return [self class];
}
@end

@implementation MultiplePicModel

@end

@implementation MultipleCarModel

@end

create model like before:

NSArray *array = [MultipleModel arrayOfModelsFromDictionaries:self.jsonArray error:&error];
NSLog(@"%@",array);

output:

(
<MultiplePicModel> 
   [foreground]: #0000ff
   [typeField]: picture
   [background]: #ff0000
</MultiplePicModel>,
<MultipleCarModel> 
   [tire]: #0000ff
   [typeField]: car
   [body]: #ff0000
</MultipleCarMode>
)

@billinghamj
Copy link
Copy Markdown
Member

Ah okay, interesting. This is basically an implementation of the polymorphism support.

This is actually something which has been discussed quite a lot. So far, we have always suggested implementing a class cluster by overriding the initWithDictionary:error: method.

See: #229 (comment)

That being said, it has been mentioned many times, so I do agree that we should consider it.

Some important factors for me:

  • it would need to work the same way for direct properties on objects, for arrays, for dictionaries, and possibly even for root objects
  • it must not conflict with the “class for collection elements” method

@heistings
Copy link
Copy Markdown
Contributor

heistings commented Mar 1, 2018

@billinghamj It looks good for me.

Implementing a class cluster by overriding the - initWithDictionary:error: method means allocating a superclass instance and then allocating a subclass one.

So, class method is crucial to this issue. Another similar way to avoid allocating twice is wrapping the + modelWithDictionary:error: method, and implementing a class cluster by overriding the method.

@heistings
Copy link
Copy Markdown
Contributor

@qdvictory

So is it seems a good idea to use the + modelWithDictionary:error: method?

@qdvictory
Copy link
Copy Markdown
Author

@billinghamj
yea,
it's can't support root objects.
it's only can be use like:

NSDictionary *d = @{@"typeField":@"picture",@"background":@"aaa",@"foreground":@"ccc"};
MultipleModel *m = [[[MultipleModel classForModel:d] alloc] initWithDictionary:d error:nil];

output:
<MultiplePicModel> 
   [foreground]: ccc
   [typeField]: picture
   [background]: aaa
</MultiplePicModel>

it must not conflict with the “class for collection elements” method

I added a bit is this PR.

@qdvictory
Copy link
Copy Markdown
Author

@heistings
I think it's a good idea. I will implement it later.

@qdvictory
Copy link
Copy Markdown
Author

@heistings @billinghamj
now support modelWithDictionary:error:

NSDictionary *d = @{@"typeField":@"picture",@"background":@"aaa",@"foreground":@"ccc"};
MultipleModel *m = [MultipleModel modelWithDictionary:d error:nil];

output:
<MultiplePicModel> 
   [foreground]: ccc
   [typeField]: picture
   [background]: aaa
</MultiplePicModel>

@heistings
Copy link
Copy Markdown
Contributor

@qdvictory It looks good for me. Overriding the + classForModel: method is easier than overriding the - initWithDictionary:error: method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants