您的位置:首页 > 移动开发 > IOS开发

预告 ARC 重写:iOS 实现的 json 数据源的 O-R Mapping

2013-12-26 17:24 260 查看
iOS 实现的 json 数据源的 O-R Mapping
太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)本文遵循“署名-非商业用途-保持一致”创作公用协议转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS、Android、Html5、Arduino、pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作。

时隔几年之久,再来看这四天写出的成果,不禁对那时的自已心生敬佩。
想来,现在看这堆风格很合理的代码,也有些难度,
因为,其中有几个 OC 的类继承的点,是不能用常规面向对象继承来理解的,
而是借鉴 Linux 底层中 C 语言实现的对象机制,逐层提取完成。
确实这一部分当时费了很多脑汁!

当时用 MRC 写成,现在 ARC 已经基本取代了 MRC,而 Swift 在今年的稍晚些时侯,也会取代 ARC 成为常规编程语言而应用于实际项目开发中,
所以,在 ARC 尚在的时侯,把这一课补上吧,别留下遗憾,真正开始了 Swift 的时侯,就不会再有心力和驱动力去使用 ARC 了。!#)*$&#^^*

本处仅为预告,至少是否真得能够重写,还看机缘吧。 
------------------------

再挖个坑,这个相对复杂一些,当时花了四天时间,在2010年的时侯,对于Objective-C 的反射机制的研究。
其中的设计思想,大多源自 Android 教父高焕堂先生的基类架构思想,我这里只是取了其中一小点点,拿到iOS上用一用。
曾经参加过高焕堂先生在我们公司讲授的近一个月的Android课程,Android上来说学到什么,都是次要的,最重要的是在架构设计思想上得到了真经。
高焕堂:台湾Android论坛主席,现任亚太地区Android技术大会主席,台湾Android领域框架开发联盟总架构师。发表100多篇Android核心技术文章,出版了6本Android专业技术书籍。专精于Android 核心框架及核心服务程序开发。

以下仅为相关核心类部分,涉及业务逻辑部分均已删除,不便透露。
其它实体类从该基类派生,各子类成员需有如下限定:
 1、实体必须继承自BaseEntity,且该实体类成员变量只能是如下类型的对象: NSString NSNumber NSDecimalNumber UIImage NSArray BaseEntity的子类  2、不允许使用NSDictionary,如确需要,可考虑定义对应实体类,且该实体类必须继承自BaseEntity  3、禁止有继承关系的类进行复合、聚集。        任何循环引用的情况均需考虑是否会造成解析死循环,比如,a对象有一个数组成员,那么该数组的元素不能是a对象及其子类;  4、       a、数组元素值为NSNull,用空字符串代替       b、成员变量值为nil,解析会自动忽略该成员       c、未在 1 中列出的类及其子类,解析会自动忽略  // 以下类型转成json均协同测试通过 数值:NSNumber 整型 长整型:最多传入10位数字,超过则溢出显示成负数 单精度 双精度 布尔 日期:NSDate 字符串:NSString 图片:UIImage 数组:NSArray 对象:BaseEntity的子类

@interface BaseEntity(Private)
//图片base64编解码方法
- (NSString *)encodeToBase64:(NSData *)toEncodeData;
- (NSData *)decodeFromBase64:(NSString *)toDecodeString;
- (NSString *)encodeUIImageToBase64:(UIImage *)toEncodeUIImage;
- (UIImage *)decodeUIImageFromBase64:(NSString *)toDecodeString;
//实体映射到键值
- (NSString *)parseAttributeType:(NSString *)Attributes;
- (NSArray *)getClassPropertys:(Class)classInstance;
- (NSArray *)getAllPropertys:(Class)classInstance;
- (NSDictionary *)getAllClassMapping:(Class)classInstance;
- (NSArray *)getPropertyList;
- (NSDictionary *)getClassMapping;
//键值映射到json
- (NSString *)generateRandomNumber;
- (NSArray *)getArrayContainSubedClass:(NSArray *)dealedArray;
- (NSDictionary *)getDictionaryContainedSubClass;
@end

@implementation BaseEntity

#pragma mark - 类生命周期

- (id)init
{
self = [super init];
if (self) {

}

return self;
}

- (void)dealloc {

[super dealloc];
}

#pragma mark - 类属性映射表:各子如需替换json中的键值名,实现该方法

+ (NSDictionary *)getMappingDic {

return [NSDictionary dictionaryWithObjectsAndKeys:@"tokenid", @"token", nil];
}

+ (NSDictionary *)dictionaryPresentationOf:(NSString *)className {

Class subClass = NSClassFromString(className);
BaseEntity *baseEntity = [[subClass alloc] init];
NSDictionary *propertyDic = [NSDictionary dictionaryWithDictionary:[baseEntity dictionaryPresentation]];
[baseEntity release];

return propertyDic;
}

+ (NSString *)JSONRepresentationOf:(NSString *)className {

Class subClass = NSClassFromString(className);
BaseEntity *baseEntity = [[subClass alloc] init];
NSString *jsonString = [NSString stringWithString:[baseEntity JSONRepresentation]];
[baseEntity release];

return jsonString;
}

#pragma mark - 图片base64编解码方法

- (NSString *)encodeToBase64:(NSData *)toEncodeData {

NSUInteger shouldLength = ([toEncodeData length] + 2) / 3 * 3;
NSUInteger base64Length = shouldLength / 3 * 4 + 1;

char *base64Bytes = malloc(base64Length);
memset(base64Bytes, 0, base64Length);

encodeBase64([toEncodeData bytes], [toEncodeData length], base64Bytes, &base64Length);

NSString *base64String = [[[NSString alloc] initWithUTF8String:base64Bytes] autorelease];

return base64String;
}

- (NSData *)decodeFromBase64:(NSString *)toDecodeString {

return nil;
}

- (NSString *)encodeUIImageToBase64:(UIImage *)toEncodeUIImage {
NSData *imageData = UIImagePNGRepresentation(toEncodeUIImage);
return [self encodeToBase64:imageData];
}

- (UIImage *)decodeUIImageFromBase64:(NSString *)toDecodeString {
return nil;
}

#pragma mark - 实体映射到键值

- (NSString *)parseAttributeType:(NSString *)Attributes {
NSRange leftRange = [Attributes rangeOfString:@"\""];
NSString *temp1 = [Attributes substringFromIndex:leftRange.location+1];
NSRange rightRange = [temp1 rangeOfString:@"\""];
NSString *temp2 = [temp1 substringToIndex:rightRange.location];

return temp2;
}

// 获取某个类自身的所有属性
- (NSArray *)getClassPropertys:(Class)classInstance {
NSMutableArray *classPropertyDics = [[NSMutableArray alloc] init];

u_int count;
objc_property_t *properties = class_copyPropertyList(classInstance, &count);
for (int i = 0; i < count ; i++) {
const char* propertyName = property_getName(properties[i]);
const char* propertyAttributes = property_getAttributes(properties[i]);
NSString *name = [NSString stringWithUTF8String:propertyName];
NSString *attribute = [NSString stringWithUTF8String:propertyAttributes];
NSString *attributeType = [self parseAttributeType:attribute];

NSMutableDictionary *propertyDic = [[NSMutableDictionary alloc] init];
[propertyDic setObject:attributeType forKey:name];
[classPropertyDics insertObject:propertyDic atIndex:0];
//[propertys addObject: propertyDic];
[propertyDic release];
}
free(properties);

return (NSArray *)classPropertyDics;
}

// 递归获取该类至其某一层父层(参数指定)的所有类的属性集合
- (NSArray *)getAllPropertys:(Class)classInstance {
NSMutableArray *allPropertys = [[[NSMutableArray alloc] init] autorelease];

if (![[[[[classInstance superclass] alloc] init] autorelease] isMemberOfClass:[BaseEntity class]]) {
NSArray *superPropertys = [self getAllPropertys:[classInstance superclass]];
[allPropertys addObjectsFromArray:superPropertys];
}

NSArray *propertys = [self getClassPropertys:classInstance];
[allPropertys addObjectsFromArray:propertys];

return allPropertys;
}

- (NSDictionary *)getAllClassMapping:(Class)classInstance {
NSMutableDictionary *allMappingDic = [[[NSMutableDictionary alloc] init] autorelease];

if (![[[[[classInstance superclass] alloc] init] autorelease] isMemberOfClass:[BaseEntity class]]) {
NSDictionary *mappingDic = [self getAllClassMapping:[classInstance superclass]];
NSArray *keys = [mappingDic allKeys];
for (NSString *key in keys) {
NSString *value = [mappingDic objectForKey:key];
[allMappingDic setObject:value forKey:key];
}
}

NSDictionary *classMappingDic = (NSDictionary *)[classInstance getMappingDic];
NSArray *keys = [classMappingDic allKeys];
for (NSString *key in keys) {
NSString *value = [classMappingDic objectForKey:key];
[allMappingDic setObject:value forKey:key];
}

return allMappingDic;
}

- (NSArray *)getPropertyList {
NSArray *propertys = [self getAllPropertys:[self class]];

return propertys;
}

- (NSDictionary *)getClassMapping {
NSDictionary *mappingDic = [self getAllClassMapping:[self class]];

return mappingDic;
}

#pragma mark - 键值映射到json

- (NSArray *)getArrayContainSubedClass:(NSArray *)dealedArray {
NSMutableArray *outArray = [[[NSMutableArray alloc] init] autorelease];

for (id element in dealedArray) {
if (NO == [element isKindOfClass:[NSNull class]]) {
//字符串
if (YES == [element isKindOfClass:[NSString class]]) {
[outArray addObject:element];
}
//数值
else if (YES == [element isKindOfClass:[NSNumber class]]) {
[outArray addObject:element];
}
//浮点型:暂未用,仅json转成对象时,浮点型会转成此类型
else if (YES == [element isKindOfClass:[NSDecimalNumber class]]) {
[outArray addObject:element];
}
//日期
else if (YES == [element isKindOfClass:[NSDate class]]) {
NSDate *attributeDateValue = (NSDate *)element;
double attributeDoubleValue = [attributeDateValue timeIntervalSince1970];
NSMutableDictionary *specialDic = [[NSMutableDictionary alloc] init];
[specialDic setObject:[NSNumber numberWithLongLong:attributeDoubleValue] forKey:@"time"];
[specialDic setObject:@"java.util.Date" forKey:@"javaClass"];
[outArray addObject:specialDic];
[specialDic release];
}
//图片
else if (YES == [element isKindOfClass:[UIImage class]]) {
NSString *base64String = [self encodeUIImageToBase64:(UIImage *)element];
[outArray addObject:base64String];
}
//数组
else if (YES == [element isKindOfClass:[NSArray class]]) {
NSArray *dealedArray = [self getArrayContainSubedClass:(NSArray *)element];
[outArray addObject:dealedArray];
}
//BaseEntity的子类
else if (YES == [element isKindOfClass:[BaseEntity class]]) {
NSDictionary *objDic = [element getDictionaryContainedSubClass];
[outArray addObject:objDic];
}
else {
//非以上类型的成员,此忽略,并提示开发人员,成员填写需进一步核实
NSLog(@"忽略并且未转换成json的数组元素:%@", element);
}
}
else {
[outArray addObject:@""];
}
}

return outArray;
}

- (NSDictionary *)getDictionaryContainedSubClass {
NSArray *propertys = [self getPropertyList];
NSDictionary *mappingDic = [self getClassMapping];

NSMutableDictionary *selfDic = [[[NSMutableDictionary alloc] init] autorelease];
for (NSDictionary *elementDic in propertys) {
NSArray *keys = [elementDic allKeys];
//正常来说,该层循环只有一次,特别情况例外(特别情况暂未知,留此接口)
for (NSString *attributeName in keys) {
//映射
NSString *mappingKeyName = [mappingDic objectForKey:attributeName];
if (nil == mappingKeyName) {
mappingKeyName = attributeName;
}

id attributeValue = [self valueForKey:attributeName];
if (nil != attributeValue) {
//字符串
if (YES == [attributeValue isKindOfClass:[NSString class]]) {
[selfDic setObject:attributeValue forKey:mappingKeyName];
}
//数值
else if (YES == [attributeValue isKindOfClass:[NSNumber class]]) {
[selfDic setObject:attributeValue forKey:mappingKeyName];
}
//浮点型:暂未用,仅json转成对象时,浮点型会转成此类型
else if (YES == [attributeValue isKindOfClass:[NSDecimalNumber class]]) {
[selfDic setObject:attributeValue forKey:mappingKeyName];
}
//日期
else if (YES == [attributeValue isKindOfClass:[NSDate class]]) {
NSDate *attributeDateValue = (NSDate *)attributeValue;
double attributeDoubleValue = [attributeDateValue timeIntervalSince1970];
NSMutableDictionary *specialDic = [[NSMutableDictionary alloc] init];
[specialDic setObject:[NSNumber numberWithLong:attributeDoubleValue] forKey:@"time"];
[specialDic setObject:@"java.util.Date" forKey:@"javaClass"];
[selfDic setObject:specialDic forKey:mappingKeyName];
[specialDic release];
}
//图片
else if (YES == [attributeValue isKindOfClass:[UIImage class]]) {
NSString *base64String = [self encodeUIImageToBase64:(UIImage *)attributeValue];
[selfDic setObject:base64String forKey:mappingKeyName];
}
//数组
else if (YES == [attributeValue isKindOfClass:[NSArray class]]) {
NSArray *outArray = [self getArrayContainSubedClass:(NSArray *)attributeValue];
[selfDic setObject:outArray forKey:mappingKeyName];
}
//BaseEntity的子类
else if (YES == [attributeValue isKindOfClass:[BaseEntity class]]) {
NSDictionary *objDic = [attributeValue getDictionaryContainedSubClass];
[selfDic setObject:objDic forKey:mappingKeyName];
}
else {
//非以上类型的成员,此忽略,并提示开发人员,成员填写需进一步核实
NSLog(@"忽略并且未转换成json的成员:%@", attributeName);
}
}
else {
[selfDic setObject:@"" forKey:mappingKeyName];
}
}
}
return selfDic;
}

- (NSDictionary *)dictionaryPresentation {
return [self getDictionaryContainedSubClass];
}

- (NSString *)JSONRepresentation {
NSDictionary *dictionaryPresentationDic = [self dictionaryPresentation];
if ([dictionaryPresentationDic respondsToSelector:@selector(JSONRepresentation)]) {
return [dictionaryPresentationDic JSONRepresentation];
}
else {
return nil;
}
}

- (NSString *)generateUuidString {
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
NSString *uuidString = (NSString*)CFUUIDCreateString(kCFAllocatorDefault, uuid);
[uuidString autorelease];
CFRelease(uuid);
return uuidString;
}

//按业务实际要求提供随机数算法,本处仅简单使用c语言随机数生成
- (NSString *)generateRandomNumber {
int value = (arc4random() % 1000000000) + 1;

return [NSString stringWithFormat:@"%d", value];
}

- (NSDictionary *)dictionaryPresentation:(NSString *)method {
if (nil != method) {
NSDictionary *businessDic = [self getDictionaryContainedSubClass];
NSString *randomString = [self generateRandomNumber];

NSMutableDictionary *resultDic = [[[NSMutableDictionary alloc] init] autorelease];
[resultDic setObject:randomString forKey:@"id"];
[resultDic setObject:method forKey:@"method"];
NSArray *params = [NSArray arrayWithObject:businessDic];
[resultDic setObject:params forKey:@"params"];

return resultDic;
}
else {
return nil;
}
}

- (NSString *)JSONRepresentation:(NSString *)method {
NSDictionary *dictionaryPresentationDic = [self dictionaryPresentation:method];
if ([dictionaryPresentationDic respondsToSelector:@selector(JSONRepresentation)]) {
return [dictionaryPresentationDic JSONRepresentation];
}
else {
return nil;
}
}

- (NSData *)JSONDataRepresentation:(NSString *)method {
NSString *resultJsonString = [self JSONRepresentation:method];

return (NSData *)[NSData dataWithBytes:[resultJsonString UTF8String] length:[resultJsonString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
}

@end

此类是在我马上要出差去北京之前的四天时间里怱忙写成,费了不少脑汁,而且还费了不少口水说服小鬼儿们使用,不过还是得益于严大神的全力支持,感谢感谢再感谢,感谢在这里工作期间,大神对我的关照和支持,别人都觉得您出差不在家了,不用提心吊胆了,真爽!我听到您不在家去差了,心情正好想反,觉得您不在家了,就好像缺点儿什么似的,只要看着您在,我默默地工作,都觉得有底,再难的问题,都觉得能解决,因为即使我解决不了,还有您给指点。
现在每每行事,遇到难题,都会回想起,您当时处事的风格,宽容、大度、淡然、从容、果断、重情义......,随便挑出几样照着做,总会有豁然开朗的心情陪伴,虽然我不愿意也不可能再回去,但总还是忘不了您这位伯乐。
哈哈哈,看官们,上面这段话,也许你们看不懂,但绝对能让我回忆起那段快乐、轻松的时光,也就是在那里,我从战术型思维转入战略型思维,这是过后一些还在那里工作的兄弟们给的评价,慢慢自已发现好像是有这样的变化。
人得学会感恩,因为你感恩,所以你能够拥抱一切,因为你乐于感恩,所以一切也会拥抱你。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐