(一)對象的分類
OC中的對象,主要有3種:instance對象(實例對象)、class對象(類對象)、meta-class對象(元類對象),我們在前兩章講的是instance對象
(1)instance對象
- instance對象就是通過類alloc出來的對象,同一個類多次alloc生成不同的實例對象,分別處在不同的內(nèi)存地址
- instance對象中包含信息:isa指針、其他成員變量
(2)class對象
- class對象是唯一的,一個類只有一個class對象
- class對象在內(nèi)存中存儲的信息主要包括:
- isa指針
- superclass指針
- 類的屬性信息(@property)、類的對象方法信息(instance method)
- 類的協(xié)議信息(protocol)、類的成員變量信息(ivar)
- ......等等
如何得到一個類的類對象呢?
ZQPerson *personInstance = [[ZQPerson alloc]init];//ZQPerson實例對象
personInstance.no = 432423;
//下面的三個都是ZQPerson的class對象(類對象)
Class personClass1 = [personInstance class];
Class personClass2 = [ZQPerson class];//不管調(diào)用多少次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對象
- 每個類在內(nèi)存中有且只有一個meta-class對象
- meta-class對象和class對象的內(nèi)存結(jié)構(gòu)是一樣的,但是用途不一樣,在內(nèi)存中存儲的信息主要包括:
- isa指針
- superclass指針
- 類的類方法信息(class method)
Class personMetaClass = object_getClass(personClass1);
NSLog(@"\nmeta-class對象:\n %p",personMetaClass);
/*
meta-class對象:
0x1000024b8
*/
內(nèi)存結(jié)構(gòu)一樣,是指class對象和meta-class對象結(jié)構(gòu)一樣,只不過存儲的信息不同,用途不同,如:class對象也有類方法信息,只是里面為空,meta-class也是對應(yīng)的;
//判斷某個對象是否是元類對象
NSLog(@"%d",class_isMetaClass(personMetaClass));//1
(4) object_getClass方法
在上面我們發(fā)現(xiàn)多次調(diào)用了object_getClass
方法,傳入的對象也不同,得到不同的結(jié)果,是為什么呢?
我們在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);//調(diào)用這個方法,繼續(xù)跟進
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對象