IOS高级教程2:反射根据变量的引用获取变量名
2014-05-08 10:20
453 查看
一、使用介绍
项目有的时候,会遇到一些特殊的处理,想要根据一个实例的引用,获取这个实例在代码中的名称。比如在处理View的坐标的时候,我们将UIView的坐标信息配置到plist文件中,我们可以设置一个key,再通过这个key来获取配置文件中的坐标等信息。有没有更简单的方法呢,或者我只想简单的用实例变量的变量名做为key。下面就介绍一种简单的,根据实例变量的引用获取实例变量名的办法。二、引用文件
第一步,我们需要引入我们需要的头文件,在需要使用的类中引用下面代码#import <objc/runtime.h>
三、运行原理
我们可以从苹果官方的开发文档中查看到详细的运行时的使用方法及API,官方并没有直接提供根据实例的引用获取实例变量名称的办法,所以我们需要自己去实现。在官方的API中我们可以找到以下几个方法
(1)Describes the instance variables declared by a class.
Ivar * class_copyIvarList(Class cls, unsigned int *outCount)
(2) Reads
the value of an instance variable in an object.
id object_getIvar(id object, Ivar ivar)
(3) Returns
the name of an instance variable.
const char * ivar_getName(Ivar ivar)
根据以上的API,我们可以根据变量的拥有者获取所有变量的Ivar,再迭代所有Ivar,每一次迭代做如下操作
根据(2)中的API,我们可以获取到当前迭代中的Ivar对应的实例变量的引用
将获取到的实例变量与传递过来的实例变量的地址比较
如果地址相同,说明当前的Ivar为传递过来实例变量的Ivar,可以通过(3)获取变量的名称并返回
四、代码
(1)根据上面的原理我们可以得到第一版本的代码,如下:- (NSString *)nameWithInstance:(id)instance { unsigned int numIvars = 0; NSString *key=nil; Ivar * ivars = class_copyIvarList([self.target class], &numIvars); for(int i = 0; i < numIvars; i++) { Ivar thisIvar = ivars[i]; if ((object_getIvar(self.target, thisIvar) == instance)) { key = [NSString stringWithUTF8String:ivar_getName(thisIvar)]; break; } } free(ivars); return key; }
(2)在测试中发现到达上面的if语句的时候,程序有的时候就会crash,经详细测试发现,每次迭代到非objective-c对象的时候,如基本数据类型,BOOL、int、float就会报错。
原因出在object_getIvar这个方法中,当遇到非objective-c对象时,并直接crash,后来查看官方解释
The value of the instance variable specified by ivar, or nil if object is nil.
并没有明确的给出遇到非对象时会crash,也并不会返回nil
我们需要进行一下修正,当遇到非objective-c的时候,需要跳过执行。最终代码如下:
- (NSString *)nameWithInstance:(id)instance { unsigned int numIvars = 0; NSString *key=nil; Ivar * ivars = class_copyIvarList([self.target class], &numIvars); for(int i = 0; i < numIvars; i++) { Ivar thisIvar = ivars[i]; const char *type = ivar_getTypeEncoding(thisIvar); NSString *stringType = [NSString stringWithCString:type encoding:NSUTF8StringEncoding]; if (![stringType hasPrefix:@"@"]) { continue; } if ((object_getIvar(self.target, thisIvar) == instance)) { key = [NSString stringWithUTF8String:ivar_getName(thisIvar)]; break; } } free(ivars); return key; }
相关文章推荐
- IOS高级教程2:反射根据变量的引用获取变量名
- IOS高级教程2:反射根据变量的引用获取变量名
- 反射根据变量的引用获取变量名
- 反射根据变量的引用获取变量名
- 根据变量的引用,获取变量名
- 【C/C++学院】0814-引用高级、引用高级增加/auto自动变量自动根据类型创建数据/Bool/Enum/newdelete全局/大数据乘法与结构体/函数模板与auto/宽字符本地化/inline
- iOS动态性(二):运行时runtime初探(强制获取并修改私有变量,强制增加及修改私有方法等)
- 22、Java入门—反射之获取获取成员变量和构造函数的信息
- 利用Java反射根据属性名获取对象值和类型代码
- java 反射机制--根据属性名获取属性值
- IOS 反射获取属性,序列化成xml
- (腾讯视频)iOS开发之视频根据url获取第一帧图片,获取任一帧图片
- iOS根据获取的月和日星座名称
- iOS动态性(二):运行时runtime初探(强制获取并修改私有变量,强制增加及修改私有方法等)
- iOS运行时获取对象的成员变量和成员方法
- ios根据日期获取年月日分秒及常用操作(问题)
- IOS高级教程1:处理1000张图片的内存优化
- DOS批处理高级教程(三) : 批处理变量和set命令详解
- java中通过反射强力获取私有变量的值
- iOS根据输入的位置获取经纬度