博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Objective-C的反射机制
阅读量:5279 次
发布时间:2019-06-14

本文共 3623 字,大约阅读时间需要 12 分钟。

从JSONModel看Objective-C的反射机制

前言

移动互联时代,JSON作为一种数据传输格式几乎随处可见。作为iOS开发者,收到一串JSON字符串要怎么处理?我想多数情况下是需要将它转成自定义的NSObject对象再使用,对于这个转换的过程,大部分人是这么做的:

1234567
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里面的属性越多,冗余的代码量也相应越多。对于这个问题,自然是有更好的解决方案,比如说这样:

12
NSError* err = nil;User* user = [[User alloc] initWithDictionary:json error:&err];

两行代码足矣,当然,实现这个功能,实际上是把很多背后的工作交给这个开源包去做了。至于其实现原理,则主要是基于的反射机制。

关于反射

《Thinking in Java》中将反射称解释为运行时的类信息,说白了就是这个类信息在编译的时候是未知的,需要在程序运行期间动态获取,而这正是我们之前试图去解决的问题。对于从网络上获取到的一段JSON字符串,在代码编译期间当然是无法知晓的。虽然这里说的是Java语言,但是对于Objective-C,这种反射机制也是同样支持的。

JSONModel中的实现

打断点记录了下JSONModel这个类中的方法调用顺序如下:

调用顺序

对象属性的获取则主要在最后一个inspectProperties方法

以下是inspectProperties方法的代码片段:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
···//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 );

在这边可以看到基本步骤如下

  1. 通过调用自身的class方法获取当前类的元数据信息
  2. 通过runtime的 class_copyPropertyList 方法取得当前类的属性列表,以指针数组的形式返回
  3. 遍历指针数组,通过property_getName获取属性名,property_getAttributes获取属性类型
  4. 使用NSScanner来扫描属性类型字符串,将类似如下的形式"T@"NSNumber",&,N,V_id",处理成NSNumber,逐个属性循环处理
  5. 将所有处理好的数据放入propertyIndex这个字典中
  6. 通过objc_setAssociatedObject将这些数据关联到kClassPropertiesKey

使用时在properties方法中这样取出属性数据:

1234567891011121314
//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中使用反射机制实现的类属性获取过程,相比常见的逐个取值赋值的方式,这种方法在代码上的确简洁优雅了很多,特别是对于使用的类属性比较复杂的情况,免除了很多不必要的代码。

转载于:https://www.cnblogs.com/sunshaowen/p/4157371.html

你可能感兴趣的文章
WPF / Win Form:多线程去修改或访问UI线程数据的方法( winform 跨线程访问UI控件 )...
查看>>
js学习笔记8
查看>>
SSH整合
查看>>
java--迭代范型化 HashMap
查看>>
mysql初级命令day01学习笔记
查看>>
CF43A Football
查看>>
DISCUZ论坛开发点滴
查看>>
CWnd *和HWnd转换 分类: VC++ ...
查看>>
JS监听手机端浏览器的后退按钮的事件方法
查看>>
note02-计算机网络
查看>>
day03-函数基础
查看>>
python——函数 20、三元表达式、列表推导式、生成器表达式
查看>>
(前端)html与css,html 8、div和span标签
查看>>
jndi
查看>>
centOS6下安装lamp
查看>>
JSP项目中使用ueditor(百度编辑器)
查看>>
前端之JavaScript笔记2
查看>>
Unique Paths
查看>>
热更新脚本C#light,ulua,Scorpio性能比较
查看>>
disconf 2.6.36 install
查看>>