Objective-C Runtime 运行时:成员变量(ivars)及属性
2015-09-06 13:29
597 查看
获取类的成员变量和属性:
(这里有篇文章写得很详细关于Runtime 运行时:/article/1225879.html)
在objc_class中,所有的成员变量、属性的信息是放在链表ivars中的。ivars是一个数组,数组中每个元素是指向Ivar(变量信息)的指针。runtime提供了丰富的函数来操作这一字段。大体上可以分为以下几类:
1.成员变量操作函数,主要包含以下函数:
class_getInstanceVariable函数,它返回一个指向包含name指定的成员变量信息的objc_ivar结构体的指针(Ivar)。
class_getClassVariable函数,目前没有找到关于Objective-C中类变量的信息,一般认为Objective-C不支持类变量。注意,返回的列表不包含父类的成员变量和属性。
Objective-C不支持往已存在的类中添加实例变量,因此不管是系统库提供的提供的类,还是我们自定义的类,都无法动态添加成员变量。但如果我们通过运行时来创建一个类的话,又应该如何给它添加成员变量呢?这时我们就可以使用class_addIvar函数了。不过需要注意的是,这个方法只能在objc_allocateClassPair函数与objc_registerClassPair之间调用。另外,这个类也不能是元类。成员变量的按字节最小对齐量是1<
class_copyIvarList函数,它返回一个指向成员变量信息的数组,数组中每个元素是指向该成员变量信息的objc_ivar结构体的指针。这个数组不包含在父类中声明的变量。outCount指针返回数组的大小。需要注意的是,我们必须使用free()来释放这个数组。
2.属性操作函数,主要包含以下函数:
这一种方法也是针对ivars来操作,不过只操作那些是属性的值。我们在后面介绍属性时会再遇到这些函数。
实例:
这段程序的输出如下:
(这里有篇文章写得很详细关于Runtime 运行时:/article/1225879.html)
在objc_class中,所有的成员变量、属性的信息是放在链表ivars中的。ivars是一个数组,数组中每个元素是指向Ivar(变量信息)的指针。runtime提供了丰富的函数来操作这一字段。大体上可以分为以下几类:
1.成员变量操作函数,主要包含以下函数:
// 获取类中指定名称实例成员变量的信息 Ivar class_getInstanceVariable ( Class cls, const char *name ); // 获取类成员变量的信息 Ivar class_getClassVariable ( Class cls, const char *name ); // 添加成员变量 BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types ); // 获取整个成员变量列表 Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
class_getInstanceVariable函数,它返回一个指向包含name指定的成员变量信息的objc_ivar结构体的指针(Ivar)。
class_getClassVariable函数,目前没有找到关于Objective-C中类变量的信息,一般认为Objective-C不支持类变量。注意,返回的列表不包含父类的成员变量和属性。
Objective-C不支持往已存在的类中添加实例变量,因此不管是系统库提供的提供的类,还是我们自定义的类,都无法动态添加成员变量。但如果我们通过运行时来创建一个类的话,又应该如何给它添加成员变量呢?这时我们就可以使用class_addIvar函数了。不过需要注意的是,这个方法只能在objc_allocateClassPair函数与objc_registerClassPair之间调用。另外,这个类也不能是元类。成员变量的按字节最小对齐量是1<
class_copyIvarList函数,它返回一个指向成员变量信息的数组,数组中每个元素是指向该成员变量信息的objc_ivar结构体的指针。这个数组不包含在父类中声明的变量。outCount指针返回数组的大小。需要注意的是,我们必须使用free()来释放这个数组。
2.属性操作函数,主要包含以下函数:
// 获取指定的属性 objc_property_t class_getProperty ( Class cls, const char *name ); // 获取属性列表 objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount ); // 为类添加属性 BOOL class_addProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount ); // 替换类的属性 void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
这一种方法也是针对ivars来操作,不过只操作那些是属性的值。我们在后面介绍属性时会再遇到这些函数。
实例:
//----------------------------------------------------------- // MyClass.h @interface MyClass : NSObject @property (nonatomic, strong) NSArray *array; @property (nonatomic, copy) NSString *string; - (void)method1; - (void)method2; + (void)classMethod1; @end //----------------------------------------------------------- // MyClass.m #import "MyClass.h" @interface MyClass () { NSInteger _instance1; NSString * _instance2; } @property (nonatomic, assign) NSUInteger integer; - (void)method3WithArg1:(NSInteger)arg1 arg2:(NSString *)arg2; @end @implementation MyClass + (void)classMethod1 { } - (void)method1 { NSLog(@"call method method1"); } - (void)method2 { } - (void)method3WithArg1:(NSInteger)arg1 arg2:(NSString *)arg2 { NSLog(@"arg1 : %ld, arg2 : %@", arg1, arg2); } @end
MyClass *myClass = [[MyClass alloc] init]; unsigned int outCount = 0; Class cls = myClass.class; // 类名 NSLog(@"class name: %s", class_getName(cls)); NSLog(@"=========================================================="); // 父类 NSLog(@"super class name: %s", class_getName(class_getSuperclass(cls))); NSLog(@"=========================================================="); // 是否是元类 NSLog(@"MyClass is %@ a meta-class", (class_isMetaClass(cls) ? @"" : @"not")); NSLog(@"=========================================================="); Class meta_class = objc_getMetaClass(class_getName(cls)); NSLog(@"%s's meta-class is %s", class_getName(cls), class_getName(meta_class)); NSLog(@"=========================================================="); // 变量实例大小 NSLog(@"instance size: %zu", class_getInstanceSize(cls)); NSLog(@"=========================================================="); // 成员变量 Ivar *ivars = class_copyIvarList(cls, &outCount); for (int i = 0; i < outCount; i++) { Ivar ivar = ivars[i]; NSLog(@"instance variable's name: %s at index: %d", ivar_getName(ivar), i); } free(ivars); Ivar string = class_getInstanceVariable(cls, "_string"); if (string != NULL) { NSLog(@"instace variable %s", ivar_getName(string)); } NSLog(@"=========================================================="); // 属性操作 objc_property_t * properties = class_copyPropertyList(cls, &outCount); for (int i = 0; i < outCount; i++) { objc_property_t property = properties[i]; NSLog(@"property's name: %s", property_getName(property)); } free(properties); objc_property_t array = class_getProperty(cls, "array"); if (array != NULL) { NSLog(@"property %s", property_getName(array)); } NSLog(@"=========================================================="); // 方法操作 Method *methods = class_copyMethodList(cls, &outCount); for (int i = 0; i < outCount; i++) { Method method = methods[i]; NSLog(@"method's signature: %s", method_getName(method)); } free(methods); Method method1 = class_getInstanceMethod(cls, @selector(method1)); if (method1 != NULL) { NSLog(@"method %s", method_getName(method1)); } Method classMethod = class_getClassMethod(cls, @selector(classMethod1)); if (classMethod != NULL) { NSLog(@"class method : %s", method_getName(classMethod)); } NSLog(@"MyClass is%@ responsd to selector: method3WithArg1:arg2:", class_respondsToSelector(cls, @selector(method3WithArg1:arg2:)) ? @"" : @" not"); IMP imp = class_getMethodImplementation(cls, @selector(method1)); imp(); NSLog(@"=========================================================="); // 协议 Protocol * __unsafe_unretained * protocols = class_copyProtocolList(cls, &outCount); Protocol * protocol; for (int i = 0; i < outCount; i++) { protocol = protocols[i]; NSLog(@"protocol name: %s", protocol_getName(protocol)); } NSLog(@"MyClass is%@ responsed to protocol %s", class_conformsToProtocol(cls, protocol) ? @"" : @" not", protocol_getName(protocol)); NSLog(@"==========================================================");
这段程序的输出如下:
2014-10-22 19:41:37.452 RuntimeTest[3189:156810] class name: MyClass 2014-10-22 19:41:37.453 RuntimeTest[3189:156810] ========================================================== 2014-10-22 19:41:37.454 RuntimeTest[3189:156810] super class name: NSObject 2014-10-22 19:41:37.454 RuntimeTest[3189:156810] ========================================================== 2014-10-22 19:41:37.454 RuntimeTest[3189:156810] MyClass is not a meta-class 2014-10-22 19:41:37.454 RuntimeTest[3189:156810] ========================================================== 2014-10-22 19:41:37.454 RuntimeTest[3189:156810] MyClass's meta-class is MyClass 2014-10-22 19:41:37.455 RuntimeTest[3189:156810] ========================================================== 2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance size: 48 2014-10-22 19:41:37.455 RuntimeTest[3189:156810] ========================================================== 2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _instance1 at index: 0 2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _instance2 at index: 1 2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _array at index: 2 2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _string at index: 3 2014-10-22 19:41:37.463 RuntimeTest[3189:156810] instance variable's name: _integer at index: 4 2014-10-22 19:41:37.463 RuntimeTest[3189:156810] instace variable _string 2014-10-22 19:41:37.463 RuntimeTest[3189:156810] ========================================================== 2014-10-22 19:41:37.463 RuntimeTest[3189:156810] property's name: array 2014-10-22 19:41:37.463 RuntimeTest[3189:156810] property's name: string 2014-10-22 19:41:37.464 RuntimeTest[3189:156810] property's name: integer 2014-10-22 19:41:37.464 RuntimeTest[3189:156810] property array 2014-10-22 19:41:37.464 RuntimeTest[3189:156810] ========================================================== 2014-10-22 19:41:37.464 RuntimeTest[3189:156810] method's signature: method1 2014-10-22 19:41:37.464 RuntimeTest[3189:156810] method's signature: method2 2014-10-22 19:41:37.464 RuntimeTest[3189:156810] method's signature: method3WithArg1:arg2: 2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: integer 2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: setInteger: 2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: array 2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: string 2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: setString: 2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: setArray: 2014-10-22 19:41:37.466 RuntimeTest[3189:156810] method's signature: .cxx_destruct 2014-10-22 19:41:37.466 RuntimeTest[3189:156810] method method1 2014-10-22 19:41:37.466 RuntimeTest[3189:156810] class method : classMethod1 2014-10-22 19:41:37.466 RuntimeTest[3189:156810] MyClass is responsd to selector: method3WithArg1:arg2: 2014-10-22 19:41:37.467 RuntimeTest[3189:156810] call method method1 2014-10-22 19:41:37.467 RuntimeTest[3189:156810] ========================================================== 2014-10-22 19:41:37.467 RuntimeTest[3189:156810] protocol name: NSCopying 2014-10-22 19:41:37.467 RuntimeTest[3189:156810] protocol name: NSCoding 2014-10-22 19:41:37.467 RuntimeTest[3189:156810] MyClass is responsed to protocol NSCoding 2014-10-22 19:41:37.468 RuntimeTest[3189:156810] ==========================================================
相关文章推荐
- 常见问题总结篇二、 对Autolayout VFL(Visual Format Language) 的扩展
- openstack kilo compute更新后报错IncompatibleObjectVersion: Version 1.2 of PciDeviceList is not supported
- java 中 List<Object []>的用法
- java基础类:Object类和Math类
- Objective-C 之NSString及常用方法
- json教程系列(3)-JSONObject的过滤设置
- json教程系列(2)-生成JSONObject的方法
- iOS7之后JavaScript与Objective-C之间的通信
- dop object 中的属性运用
- OC基础教程1-Hello Wrold(OS X版)
- JSONObject与JSONArray的使用
- Objective-C 面向对象(类II)
- error: allocating an object of abstract class type
- Effective Objective-C 2.0 第5条:用枚举表示状态、选项、状态码
- Objective-C 内存管理
- lodash 中文学习拾零之 Object篇
- swift详解之十-------------异常处理、类型转换 ( Any and AnyObject )
- 黑马程序员——Objective-C之面向对象
- Objective-c 循环引用
- Flex中用RemoteObject与java后台通信