來歷
寫給想玩runtime卻又難以開啟征程的小伙伴雏门。這個(gè)函數(shù)是包含在頭文件<objc/message.h>當(dāng)中的一個(gè)支撐起整個(gè)消息發(fā)送機(jī)制的關(guān)鍵函數(shù)束莫。也和OC的runtime機(jī)制密不可分增拥。所以隨著64位操作系統(tǒng)的出現(xiàn)runtime出現(xiàn)了歷史變更涨冀,objc_msgSend也出現(xiàn)了變化勺像。
老版本
所謂老版本也就是蘋果在未推出新版runtime之前,此時(shí)碼農(nóng)們可以肆意的使用objc_msgSend()函數(shù)胧辽,系統(tǒng)中就默認(rèn)許可了這樣函數(shù)的存在:
objc_msgSend(receiver, selector, arg1, arg2, …);
新版本
看系統(tǒng)API發(fā)現(xiàn)只剩下一個(gè)不帶參數(shù)的objc_msgSend函數(shù)公黑,寶寶心里苦啊邑商,objc_msgSend不帶參數(shù)我用它干什么,但我們知道這個(gè)函數(shù)是關(guān)鍵不可能不能調(diào)用凡蚜。于是發(fā)現(xiàn)將這個(gè)函數(shù)看成c語言的函數(shù)聲明就可以通過強(qiáng)制轉(zhuǎn)化解決這個(gè)問題人断,比如這樣
((void ()(id, SEL , NSString))objc_msgSend)((id)p, @selector(setName:),@"33");
返回結(jié)構(gòu)體時(shí)朝蜘,不能使用objc_msgSend恶迈,而是要使用objc_msgSend_stret,否則會(huì)crash
用objc_msgSend_stret
來發(fā)送返回值類型為結(jié)構(gòu)體的消息谱醇,使用objc_msgSend_fpret
來發(fā)送返回值類型為浮點(diǎn)類型的消息蝉绷,而又在一些處理器上鸭廷,還得使用objc_msgSend_fp2ret
來發(fā)送返回值類型為浮點(diǎn)類型的消息。
頭部就是將這個(gè)函數(shù)轉(zhuǎn)化成了合適的函數(shù)指針即((void ()(id, SEL , NSString))熔吗,不清楚可以Google函數(shù)指針辆床,這樣就可以解決掉不能調(diào)用objc_msgSend函數(shù)問題,其它變更后續(xù)更新桅狠!
面試小知識
IMP是一個(gè)函數(shù)指針讼载,SEL是一個(gè)結(jié)構(gòu)體變量,核心是一個(gè)字符串可以通過
SEL sel=NSSelectorFromString(@"method");
來創(chuàng)建SEL對象中跌,當(dāng)然常見的還是@selector()方法咨堤。objc_msgSend消息發(fā)送會(huì)有倆個(gè)隱藏參數(shù)self和_cmd