咱們先來解釋一下蘋果官方給開發者提供的這張圖bash
例如咱們建立個本身的類 LWPerson *person = [[LWPerson alloc] init];
每一個類都有本身的isa
,它指向對應的了[LWPerson Class]
,[LWPerson Class]
也有本身的isa
,它則指向對應的元類meta
;這裏解釋一下兩個問題spa
Q : Instance(類對象),class(類),meta(即meta-class元類) 裏面各存着這麼設計
A : Instance
存着一個isa
指向class
,還存着本身的成員變量;class
裏存有isa
,superclass
,屬性、對象方法、協議、成員變量等;meta
裏存在isa,superclass
,類方法等;如圖(圖片引用自李明傑老師)3d
isa
要這樣指來指去,這樣有什麼好處
A : 例如這段代碼指針
LWPerson *person = [[LWPerson alloc] init];
person.age = 20;
persom.height = 180;
[person sing];
[person dance];
[person rap];
複製代碼
其中age
和height
都是每一個LWPerson
私有的,每建立一個LWPerson
均可能不同,可是sing
,dance
,rap
方法是每個LWPerson
共有。因此當建立LWPerson
對象後,只需isa
和成員變量,全部的方法都放在LWPerson
的類裏,對象經過isa
找到對應類的的方法,這樣能夠大大的節省LWPerson
對象所佔用的內存。這裏LWPerson
類的isa
指向LWPerson
的元類,類方法就存在元類裏,也很好的解釋了通常狀況下 類方法爲何不能使自己的成員變量,由於存在類對象上;code
接回以前的繼續說:每一個類都存有一個superclass
指針,這很好理解,子類若是找不到對應的方法,便會順着superclass
指針找到對應的父類。meta
的也同樣自己沒有的類方法也會去尋找父類的類方法,這樣一直一級一級往上傳,一直傳到Root Class
, Root Class
的元類比較特殊,蘋果設計它的isa
指向本身,superclass
指向Root Class
,若是Root Class
也找不到方法,就會報一個咱們很熟悉的錯誤 unrecognized selector sent to instance 0x600001a3a5b0
cdn
可能上面說的比較多比較亂,咱們能夠舉個栗子再捋一次 首先,咱們建立個類LWPerson
繼承於NSObject
。對象
LWPerson *person = [[LWPerson alloc] init];
複製代碼
在建立LWPerson
的時候,咱們用的[LWPerson alloc]
本質就是 LWPerson
類經過isa
去meta
裏找類方法,可是找不到!就再經過meta
的superclass
找到它的父meta
即NSObject
的meta
, NSObject
的類方咱們很容易就能夠找到alloc
。init
也是同理,咱們在[LWPerson alloc]
後,它實際上返回的是一個LWPerson
的對象,它自己也沒有init
對象方法,因此找它的父類NSObject
的對象方法init
blog
咱們也能夠在LWPerson.h
中聲明一個-(void)sing
方法,但不寫實現,這樣person
對象就會去LWPerson
的類裏找sing
方法,但沒實現sing
方法,就會順着superclass
去NSObject
到對象方法,但NSObject
也沒有sing
方法,因此繼續往上找到了Root Class
,但Root Class
也沒有sing
方法,因此指向nil
,系統報錯 unrecognized selector sent to instance
。 繼承