标签:http io ar os 使用 sp for java strong
移动互联时代,JSON作为一种数据传输格式几乎随处可见。作为iOS开发者,收到一串JSON字符串要怎么处理?我想多数情况下是需要将它转成自定义的NSObject对象再使用,对于这个转换的过程,大部分人是这么做的:
1 2 3 4 5 6 7 |
NSDictionary* json = (fetch from Internet) ...
User* user=[[User alloc] init];
user.userId =[json objectForKey:@"userId"];
user.nick= [json objectForKey:@"nick"];
user.image = [json objectForKey:@"image"];
user.age = [json objectForKey:@"age"];
...
|
这样的代码没错,但也绝对说不上优雅,model里面的属性越多,冗余的代码量也相应越多。对于这个问题,自然是有更好的解决方案,比如说这样:
1 2 |
NSError* err = nil;
User* user = [[User alloc] initWithDictionary:json error:&err];
|
两行代码足矣,当然,实现这个功能,实际上是把很多背后的工作交给JSONModel这个开源包去做了。至于其实现原理,则主要是基于Objective-C Runtime的反射机制。
《Thinking in Java》中将反射称解释为运行时的类信息,说白了就是这个类信息在编译的时候是未知的,需要在程序运行期间动态获取,而这正是我们之前试图去解决的问题。对于从网络上获取到的一段JSON字符串,在代码编译期间当然是无法知晓的。虽然这里说的是Java语言,但是对于Objective-C,这种反射机制也是同样支持的。
打断点记录了下JSONModel这个类中的方法调用顺序如下:
对象属性的获取则主要在最后一个inspectProperties方法
以下是inspectProperties方法的代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
···
//inspects the class, get‘s a list of the class properties
-(void)__inspectProperties
{
//JMLog(@"Inspect class: %@", [self class]);
NSMutableDictionary* propertyIndex = [NSMutableDictionary dictionary];
//temp variables for the loops
Class class = [self class];
NSScanner* scanner = nil;
NSString* propertyType = nil;
// inspect inherited properties up to the JSONModel class
while (class != [JSONModel class]) {
//JMLog(@"inspecting: %@", NSStringFromClass(class));
unsigned int propertyCount;
objc_property_t *properties = class_copyPropertyList(class, &propertyCount);
//loop over the class properties
for (unsigned int i = 0; i < propertyCount; i++) {
JSONModelClassProperty* p = [[JSONModelClassProperty alloc] init];
//get property name
objc_property_t property = properties[i];
const char *propertyName = property_getName(property);
p.name = [NSString stringWithUTF8String:propertyName];
//JMLog(@"property: %@", p.name);
//get property attributes
const char *attrs = property_getAttributes(property);
NSString* propertyAttributes = [NSString stringWithUTF8String:attrs];
if ([propertyAttributes hasPrefix:@"Tc,"]) {
//mask BOOLs as structs so they can have custom convertors
p.structName = @"BOOL";
}
scanner = [NSScanner scannerWithString: propertyAttributes];
//JMLog(@"attr: %@", [NSString stringWithCString:attrs encoding:NSUTF8StringEncoding]);
[scanner scanUpToString:@"T" intoString: nil];
[scanner scanString:@"T" intoString:nil];
···
//finally store the property index in the static property index
objc_setAssociatedObject(self.class,
&kClassPropertiesKey,
[propertyIndex copy],
OBJC_ASSOCIATION_RETAIN // This is atomic
);
|
在这边可以看到基本步骤如下
使用时在properties方法中这样取出属性数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//returns a list of the model‘s properties
-(NSArray*)__properties__
{
//fetch the associated object
NSDictionary* classProperties = objc_getAssociatedObject(self.class, &kClassPropertiesKey);
if (classProperties) return [classProperties allValues];
//if here, the class needs to inspect itself
[self __setup__];
//return the property list
classProperties = objc_getAssociatedObject(self.class, &kClassPropertiesKey);
return [classProperties allValues];
}
|
以上就是JSONModel中使用反射机制实现的类属性获取过程,相比常见的逐个取值赋值的方式,这种方法在代码上的确简洁优雅了很多,特别是对于使用的类属性比较复杂的情况,免除了很多不必要的代码。
标签:http io ar os 使用 sp for java strong
原文地址:http://www.cnblogs.com/sunshaowen/p/4157371.html