Skip to content

Instantly share code, notes, and snippets.

@huacnlee
Created April 18, 2013 11:32
Show Gist options
  • Save huacnlee/5412056 to your computer and use it in GitHub Desktop.
Save huacnlee/5412056 to your computer and use it in GitHub Desktop.
BaseModel,用于 JSON 转 Objective-C Model
#import <Foundation/Foundation.h>
#import "XMImageURL.h"
enum {
// 保密
XMGenderUnknow = 0,
// 男
XMGenderMale = 1,
// 女
XMGenderFemale = 2,
};
// 用户性别
typedef int XMGender;
enum {
XMRankInfoTypeSong = 1,
XMRankInfoTypeAlbum,
XMRankInfoTypeArtist,
};
// Rank.getInfo 查询参数类型
typedef int XMRankInfoType;
@interface XMBaseModel : NSObject <NSCoding>
+ (NSDictionary *) keysMapping;
+ (id)modelWithResponseDict:(NSDictionary *)dict;
// 将 API 返回的 str 的性别转换成 XMGender
+ (XMGender) xmGenderWithResponseString: (NSString *) str;
@end
#import "XMBaseModel.h"
#import "NSURL+XMAddition.h"
#import <objc/runtime.h>
@implementation XMBaseModel
+ (XMGender) xmGenderWithResponseString: (NSString *) str {
XMGender gender = XMGenderUnknow;
gender = XMGenderUnknow;
if ([str isEqualToString:@"M"]) {
gender = XMGenderMale;
}
else if ([str isEqualToString:@"F"]) {
gender = XMGenderFemale;
}
return gender;
}
// 自动将 JSON 里面的值根据 keyMappings 的定义填充到对应的属性里面,并生成一个对象
// 此方法将不会处理 NSArray 的内容
+ (id)modelWithResponseDict:(NSDictionary *)dict {
id obj = [self new];
for (NSString *originKey in [[self keysMapping] allKeys]) {
// OC 的 key
NSString *key = [[self keysMapping] objectForKey:originKey];
// JSON 的值
if ([[[dict allKeys] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF == %@",originKey]] count] == 0) {
// 跳过结果里面没有的 key
continue;
}
id originVal = dict[originKey];
// 得到 OC 那个 Key 的类型
if ([originVal isKindOfClass:[NSString class]]) {
// NSString
if ([obj propertyIsNSUInteger:key]) {
// NSUInteger & int
[obj setValue:[NSNumber numberWithUnsignedInteger:(NSUInteger) [originVal integerValue]] forKey:key];
}
else if ([obj propertyIsBoolean:key]) {
// BOOL
if ([originVal isEqualToString:@"1"] || [originVal isEqualToString:@"yes"] || [originVal isEqualToString:@"true"]) {
[obj setValue:[NSNumber numberWithBool:true] forKey:key];
}
else {
[obj setValue:[NSNumber numberWithBool:false] forKey:key];
}
}
else if ([obj propertyIsNSURL:key]) {
// NSURL
[obj setValue:[NSURL URLWithEscapedString:originVal] forKey:key];
}
else if ([obj propertyIsXMImageURL:key]) {
XMImageURLType imageUrlType = XMImageURLTypeAlbum;
if ([[obj className] isEqualToString:@"XMAlbum"]) {
imageUrlType = XMImageURLTypeAlbum;
}
else if ([[obj className] isEqualToString:@"XMSong"]) {
imageUrlType = XMImageURLTypeSong;
}
else if ([[obj className] isEqualToString:@"XMUser"]) {
imageUrlType = XMImageURLTypeUser;
}
else if ([[obj className] isEqualToString:@"XMCollect"]) {
imageUrlType = XMImageURLTypeCollect;
}
else if ([[obj className] isEqualToString:@"XMRadio"]) {
imageUrlType = XMImageURLTypeRadio;
}
else if ([[obj className] isEqualToString:@"XMArtist"]) {
imageUrlType = XMImageURLTypeArtist;
}
[obj setValue:[XMImageURL urlWithType:imageUrlType url:originVal] forKey:key];
}
else {
// NSString
[obj setValue:originVal forKey:key];
}
}
else if ([originVal isKindOfClass:[NSNumber class]]) {
if ([obj propertyIsDate:key]) {
[obj setValue:[NSDate dateWithTimeIntervalSince1970:[originVal integerValue]] forKey:key];
}
else {
[obj setValue:originVal forKey:key];
}
}
}
return obj;
}
- (BOOL) propertyIsNSString: (NSString *) property {
return ([[self.class typeForProperty:property] isEqualToString:@"@\"NSString\""]);
}
- (BOOL) propertyIsDate: (NSString *) property {
return ([[self.class typeForProperty:property] isEqualToString:@"@\"NSDate\""]);
}
- (BOOL) propertyIsNSUInteger: (NSString *) property {
return ([[self.class typeForProperty:property] isEqualToString:@"Q"]);
}
- (BOOL) propertyIsBoolean: (NSString *) property {
return ([[self.class typeForProperty:property] isEqualToString:@"c"]);
}
- (BOOL) propertyIsNSURL: (NSString *) property {
return ([[self.class typeForProperty:property] isEqualToString:@"@\"NSURL\""]);
}
- (BOOL) propertyIsXMImageURL: (NSString *) property {
return ([[self.class typeForProperty:property] isEqualToString:@"@\"XMImageURL\""]);
}
+ (NSString *) typeForProperty:(NSString *)prop {
NSString *result = nil;
objc_property_t property = class_getProperty(self, [prop UTF8String]);
if (!property)
return nil;
// This will return some garbage like "Ti,GgetFoo,SsetFoo:,Vproperty"
// See https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html
NSString *atts = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];
for (NSString *att in [atts componentsSeparatedByString:@","]) {
if ([att hasPrefix:@"T"]) {
result = [att substringFromIndex:1];
// NSLog(@"---- %@ || %@", atts, result);
return result;
}
}
return nil;
}
+ (NSDictionary *)keysMapping {
return @{};
}
#pragma mark - NSCoding
- (id)initWithCoder:(NSCoder *)aDecoder {
NSArray *keys = [[self.class keysMapping] allValues];
if ([aDecoder allowsKeyedCoding]) {
for (NSString *key in keys) {
[self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
}
} else {
for (NSString *key in keys) {
[self setValue:[aDecoder decodeObject] forKey:key];
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
NSArray *keys = [[self.class keysMapping] allValues];
if ([aCoder allowsKeyedCoding]) {
for (NSString *key in keys) {
[aCoder encodeObject:[self valueForKey:key] forKey:key];
}
} else {
for (NSString *key in keys) {
[aCoder encodeObject:[self valueForKey:key]];
}
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment