用Objective-C 等面向对象编程语言时,“对象”(object) 就是“基本构造单元”(building block),开发者可以通过对象来存储并传递数据。
Objective-C 中的对象总的来说可以分为两种:类对象和实例对象。在运行期程序库的头文件中,
实例对象的定义是这样的:
struct objc_object {
Class isa ;
};·
类对象的定义是这样的:
typedef struct objc_class *Class;
struct objc_class {
Class isa;
Class super_class ;
...
}
可以看出,不管是实例对象还是类对象都有一个 isa 成员变量,
- 实例对象中的 isa 指向类结构称作 class(普通的),class 结构存储类的普通成员变量与普通成员方法(-开头的方法)
- 类对象中的 isa 指向类结构被称作 metaclass , metaclass 存储类的类成员变量与类成员方法(+开头的方法)
⚠️注意⚠️:OC语法里面,并不存在类成员变量这个概念。虽然 @property 中可以添加 class 描述,但是并不会生成类成员变量。
常用API
获取变量信息
在JSON转Model 中需要获取对象的所有属性:
unsigned int count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for(int i = 0; i < count; i++) {
objc_property_t property = properties[i];
NSLog(@"name:%s attributes:%s",property_getName(property),property_getAttributes(property));
}
free(properties);
获取到的只是当前类的属性列表,如果需要获取父类的需要自行向上遍历。
上面获取到的只是对象的属性列表,如果想要获取对象的成员列表,
unsigned int count;
Ivar *ivars = class_copyIvarList([self class], &count);
for(int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
const char *ivarName = ivar_getName(ivar);
const char *ivarType = ivar_getTypeEncoding(ivar);
NSLog(@"实例变量名为:%s 字符串类型为:%s", ivarName, ivarType);
}
free(ivars);
除了获取成员变量列表的,还有通过指定名字获取变量信息的方法:
Ivar _Nullable
class_getInstanceVariable(Class _Nullable cls, const char * _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
// 由于在OC语法里面,并不存在类变量这个概念,所以,这个方法并没有什么用,
Ivar _Nullable
class_getClassVariable(Class _Nullable cls, const char * _Nonnull name)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
获取方法信息
除了获取变量信息,还能会获取到方法列表
unsigned int methodCount =0;
Method* methodList = class_copyMethodList([self class],&methodCount);
for(int i = 0; i < methodCount; i++) {
Method temp = methodList[i];
const char* name_s =sel_getName(method_getName(temp));
int arguments = method_getNumberOfArguments(temp);
const char* encoding =method_getTypeEncoding(temp);
NSLog(@"方法名:%@,参数个数:%d,编码方式:%@",[NSString stringWithUTF8String:name_s],
arguments,
[NSString stringWithUTF8String:encoding]);
}
free(methodList);
这里的方法就可以分实例方法和类方法,关键在于 class_copyMethodList
的对象,如果换成下面的方式,获取到的就是类方法列表
// 获取到的是 metaclass
Class cls = object_getClass([self class]);
Method* methodList = class_copyMethodList(cls,&methodCount);
对于 [self class] & object_getClass(self)
的区别:
self 为实例对象 | self 为类对象 | |
---|---|---|
[self class] | 类对象(等价于object_getClass) | 类对象(自身) |
object_getClass(self) | 类对象 | 元类 |