(一)对象的分类
OC中的对象,主要有3种:instance对象(实例对象)、class对象(类对象)、meta-class对象(元类对象),我们在前两章讲的是instance对象
(1)instance对象
- instance对象就是通过类alloc出来的对象,同一个类多次alloc生成不同的实例对象,分别处在不同的内存地址
- instance对象中包含信息:isa指针、其他成员变量
(2)class对象
- class对象是唯一的,一个类只有一个class对象
- class对象在内存中存储的信息主要包括:
- isa指针
- superclass指针
- 类的属性信息(@property)、类的对象方法信息(instance method)
- 类的协议信息(protocol)、类的成员变量信息(ivar)
- ......等等
如何得到一个类的类对象呢?
ZQPerson *personInstance = [[ZQPerson alloc]init];//ZQPerson实例对象
personInstance.no = 432423;
//下面的三个都是ZQPerson的class对象(类对象)
Class personClass1 = [personInstance class];
Class personClass2 = [ZQPerson class];//不管调用多少次class方法都只能获取类对象
Class personClass3 = object_getClass(personInstance);//Runtime API
NSLog(@"\nclass对象:\n %p \n %p \n %p",personClass1,personClass2,personClass3);//
/*
instance对象:
0x10060ffb0
class对象:地址都相同
0x1000024c0
0x1000024c0
0x1000024c0
*/
(3)meta-class对象
- 每个类在内存中有且只有一个meta-class对象
- meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括:
- isa指针
- superclass指针
- 类的类方法信息(class method)
Class personMetaClass = object_getClass(personClass1);
NSLog(@"\nmeta-class对象:\n %p",personMetaClass);
/*
meta-class对象:
0x1000024b8
*/
内存结构一样,是指class对象和meta-class对象结构一样,只不过存储的信息不同,用途不同,如:class对象也有类方法信息,只是里面为空,meta-class也是对应的;
//判断某个对象是否是元类对象
NSLog(@"%d",class_isMetaClass(personMetaClass));//1
(4) object_getClass方法
在上面我们发现多次调用了object_getClass
方法,传入的对象也不同,得到不同的结果,是为什么呢?
我们在runtime源码objc-class.mm
中可以找到:
Class object_getClass(id obj)
{
//1.如果传入的是istance对象,返回class对象
//2.如果传入的是class对象,返回的是meta-class对象
//3.如果传入的是meta-class,返回NSObject(基类)的meta-class对象
if (obj) return obj->getIsa();
else return Nil;
}
(5) objc_getClass方法
我们再查看一下objc_getClass
方法:
Class objc_getClass(const char *aClassName)
{
if (!aClassName) return Nil;
// NO unconnected, YES class handler
return look_up_class(aClassName, NO, YES);
}
Class
look_up_class(const char *name,
bool includeUnconnected __attribute__((unused)),
bool includeClassHandler __attribute__((unused)))
{
if (!name) return nil;
Class result;
bool unrealized;
{
runtimeLock.lock();
result = getClassExceptSomeSwift(name);//调用这个方法,继续跟进
unrealized = result && !result->isRealized();
if (unrealized) {
result = realizeClassMaybeSwiftAndUnlock(result, runtimeLock);
// runtimeLock is now unlocked
} else {
runtimeLock.unlock();
}
}
...//省略代码
return result;
}
static Class getClassExceptSomeSwift(const char *name)
{
runtimeLock.assertLocked();
// Try name as-is
Class result = getClass_impl(name);//获取类对象
if (result) return result;
// Try Swift-mangled equivalent of the given name.
if (char *swName = copySwiftV1MangledName(name)) {
result = getClass_impl(swName);
free(swName);
return result;
}
return nil;
}
我们可以看出,objc_getClass
方法传入一个类名,返回的是class对象,无法获取meta-class对象