iOS-底層-OC對(duì)象的分類

在上一篇文章中,我們講了NSObject本質(zhì),其實(shí)上一篇文章講的是實(shí)例對(duì)象

Objective-C中的對(duì)象,簡(jiǎn)稱OC對(duì)象,主要可以分為3種:

instance對(duì)象(實(shí)例對(duì)象)
class對(duì)象(類對(duì)象)
meta-class對(duì)象(元類對(duì)象)

一. instance對(duì)象(實(shí)例對(duì)象)

instance對(duì)象就是通過(guò)類alloc出來(lái)的對(duì)象,每次調(diào)用alloc都會(huì)產(chǎn)生新的instance對(duì)象,分別占據(jù)著兩塊不同的內(nèi)存

instance對(duì)象在內(nèi)存中存儲(chǔ)的信息包括:isa指針和其他成員變量

比如有如下類:

@interface Person : NSObject
{
@public
int _age;
}
@end

Person *p1 = [[Person alloc] init];
p1->_age = 3;
Person *p2 = [[Person alloc] init];
p2->_age = 4;

那么p1和p2在內(nèi)存中的結(jié)構(gòu)為:

實(shí)例對(duì)象.png

二. class對(duì)象(類對(duì)象)

每個(gè)類在內(nèi)存中有且只有一個(gè)class對(duì)象

如何獲取class對(duì)象:

NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];

//獲取類對(duì)象的三種方式 ,并且類對(duì)象是唯一的
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];

//實(shí)例對(duì)象地址不一樣
NSLog(@"%p %p",
      object1,
      object2);
//0x100534680 0x100534490

//類對(duì)象地址一樣的,是唯一的 
NSLog(@"%p %p %p %p %p",
      objectClass1,
      objectClass2,
      objectClass3,
      objectClass4,
      objectClass5);
// 0x7fff97e99140 0x7fff97e99140 0x7fff97e99140 0x7fff97e99140 0x7fff97e99140

上面代碼objectClass1~objectClass5都是NSObject的class對(duì)象(類對(duì)象),它們是同一個(gè)對(duì)象。

注意:
class方法返回的一直是class類對(duì)象,不管你調(diào)用多少次,也不會(huì)得到元類對(duì)象

Class objectMetaClass2 = [[[NSObject class] class] class];  //還是類對(duì)象

獲取class對(duì)象的三種方式

Class objectClass1 = [object1 class]; //對(duì)象的class方法
Class objectClass2 = [NSObject class]; //類的class方法
Class objectClass3 = object_getClass(object1); //傳入對(duì)象

class對(duì)象在內(nèi)存中存儲(chǔ)的信息主要包括:

isa指針
superclass指針
類的屬性信息(@property)、類的成員變量信息(ivar)
類的協(xié)議信息(protocol)、類的對(duì)象方法信息(instance method)
......

如下圖:

class對(duì)象.png

三. meta-class對(duì)象(元類對(duì)象)

每個(gè)類在內(nèi)存中有且只有一個(gè)meta-class對(duì)象

獲取meta-class對(duì)象,只有一種方法:

Class objectMetaClass = object_getClass([NSObject class]);//傳入一個(gè)class對(duì)象

objectMetaClass是NSObject的meta-class對(duì)象(元類對(duì)象)

注意:

  1. 將類對(duì)象當(dāng)做參數(shù)傳入object_getClass,獲得元類對(duì)象
  2. 類對(duì)象和元類對(duì)象都是Class類型的

meta-class對(duì)象和class對(duì)象的內(nèi)存結(jié)構(gòu)是一樣的,但是用途不一樣,在內(nèi)存中存儲(chǔ)的信息主要包括:

isa指針
superclass指針
類的類方法信息(class method)
......

看下圖你就明不白了,為什么meta-class對(duì)象和class對(duì)象的內(nèi)存結(jié)構(gòu)是一樣的,但是存儲(chǔ)的信息不一樣,因?yàn)樗麄兊淖饔貌灰粯?/p>

元類對(duì)象.png

補(bǔ)充:class_isMetaClass(objectMetaClass)可以判斷是不是元類對(duì)象

四. 查看object_getClass函數(shù)底層是如何實(shí)現(xiàn)的

1. object_getClass

在objc4中搜索函數(shù)名,找到了object_getClass的底層實(shí)現(xiàn)

Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

可以發(fā)現(xiàn),返回的是isa,所以:
如果傳進(jìn)來(lái)的是instance對(duì)象,返回class類對(duì)象
如果傳進(jìn)來(lái)的是class類對(duì)象,返回metra-class元類對(duì)象
如果傳進(jìn)來(lái)的是metra-class對(duì)象,返回NSObject(基類)的metra-class對(duì)象

2. objc_getClass

順便查看一下objc_getClass函數(shù)底層實(shí)現(xiàn),這個(gè)不太好分析,直接記結(jié)論:objc_getClass函數(shù)傳入一個(gè)字符串類名,返回一個(gè)類對(duì)象

Class objc_getClass(const char *aClassName)
{
    //這個(gè)方法是
    if (!aClassName) return Nil;

    // NO unconnected, YES class handler
    return look_up_class(aClassName, NO, YES);
}

3. - (Class)class、+ (Class)class

它們的底層實(shí)現(xiàn):

 - (Class) {
     return self->isa;
 }
//如果是對(duì)象方法,返回isa就返回了當(dāng)前的類對(duì)象

 + (Class) {
     return self;
 }
//如果是類方法,返回自己就是類對(duì)象

綜上,這兩個(gè)class方法返回的就是類對(duì)象

Demo地址:OC對(duì)象的分類

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。