當(dāng)我們重寫父類init方法時(shí),按照蘋果官方文檔的要求寫法為:
- (instancetype)init{
????? if (self = [super init]){
????????? //寫上初始化的代碼
???? }
??? return self;
}
我也每次都是按照這個(gè)規(guī)范來寫的凉敲,但是問我為何這樣寫瞬間就懵逼了穗熬,最近學(xué)習(xí)runtime谁不,受到了啟發(fā),下面我把我的理解分享給大家颠放,不一定完全準(zhǔn)確,純個(gè)人理解,歡迎斧正痛阻!
首先比較疑惑的地方:
self = [super init]油够,看起來不就是子類self指針指向了父類super嗎蚁袭?
1.要搞明白這個(gè)疑惑,首先得弄清楚self石咬,super這兩個(gè)關(guān)鍵字的含義揩悄。
self: 代表當(dāng)前方法的調(diào)用者,在對(duì)象方法中鬼悠,self代表著"當(dāng)前對(duì)象"; 在類方法中self代表當(dāng)前類删性。學(xué)習(xí)過運(yùn)行時(shí)都應(yīng)該知道oc里面的方法底層實(shí)現(xiàn)對(duì)應(yīng)的是函數(shù)指針(IMP),所有的函數(shù)指針都會(huì)默認(rèn)自帶2個(gè)參數(shù)亏娜,分別為id self和SEL _cmd;
super:僅僅只是一個(gè)“編譯器指示符”,作用就是告訴編譯器镇匀,去self的super類中(self的父類中)去找相應(yīng)的方法照藻,而不是父類自己去調(diào)用某方法。并不能理解super就是self的父類汗侵。superclass才是獲取方法調(diào)用者父類幸缕。
2. if (self = [super init]){}都干了些什么?
?????? if(self = [super init]){}
拆解開為
???? ? self = [super init]
?????? if (self != nil){}
現(xiàn)在我們梳理一下這個(gè)流程晰韵,首先子類要重寫初始化init方法发乔,按上面的步驟寫完,如何子類調(diào)用雪猪,假如這個(gè)子類叫QLSon,父類叫QLFather栏尚。
(1)QLSon *son = [QLSon alloc];
? (2)?? son = [son init]; 通過運(yùn)行時(shí)轉(zhuǎn)換為:objc_msgSend(son, @selector(init));
? (3)?? 調(diào)用這一步的時(shí)候就會(huì)進(jìn)入到重寫init的方法實(shí)現(xiàn)中,然后就會(huì)調(diào)用self = [super init]只恨;
? (4)? [super init]就是去調(diào)用self的父類中的init方法译仗,通過運(yùn)行時(shí)轉(zhuǎn)換為:objc_msgSendSuper ( struct objc_super *super, SEL op, ... );
? ? ? ? 參數(shù)一:struct objc_super *super說明
??????????????????? struct objc_super {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __unsafe_unretained id receiver;? //消息的實(shí)際接收者
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __unsafe_unretained Class super_class; //當(dāng)前類的父類
??????????????????? };
當(dāng)我們使用super來接收消息時(shí),編譯器會(huì)生成一個(gè)objc_super結(jié)構(gòu)體官觅。這個(gè)結(jié)構(gòu)體的receiver就是QLSon對(duì)象son纵菌;superClass代表QLSon的父類QLFather。
objc_msgSendSuper([son superclass], @selector(init))該函數(shù)實(shí)際的操作是:從struct objc_super結(jié)構(gòu)體指向的superClass的方法列表開始查找叫init的selector休涤,找到后再以struct objc_super結(jié)構(gòu)體的receiver去調(diào)用這個(gè)selector咱圆,而此時(shí)的操作流程就是如下方式了。
?????????????? objc_msgSend(objc_super->receiver, @selector(init))
? ? ? ? ? ? ? 由于objc_super->receiver就是self本身功氨,所以該方法實(shí)際與下面這個(gè)調(diào)用是相同的:
? ? ? ? ? ? ? objc_msgSend(self, @selector(init))
3.為什么要 self =? [super init];
??????????? 符合oc 繼承類 初始化規(guī)范 super 同樣也是這樣序苏,? [super init]? 去self 的super 中調(diào)用init? ? super 調(diào)用 superSuper 的init 。直到根類 NSObject 中的init ,
根類中init 負(fù)責(zé)初始化 內(nèi)存區(qū)域向里面添加 一些必要的屬性捷凄,返回這樣延著繼承鏈 初始化的內(nèi)存指針 被從上 到 下傳遞忱详,在不同的子類中向塊內(nèi)存添加 子類必要的屬性,直到 我們的 A 類中 得到內(nèi)存指針跺涤,賦值給self 參數(shù)踱阿, 在if (self){//添加A的屬性 }
4.示例代碼
日志輸入: