讀編寫高質(zhì)量iOS與OS X代碼的52個有效方法 (11-20章)
11:理解objc_msgSend的作用
(1):objc_msgSend:消息傳遞機(jī)制中的核心函數(shù)(就是當(dāng)oc調(diào)用方法后,編譯器會把此消息轉(zhuǎn)換為一條標(biāo)準(zhǔn)的C語言函數(shù),就是objc_msgSecnd).
原型:void objc_msgSend(id self, SEL cmd,…)//這是個參數(shù)個數(shù)可變得函數(shù). 第一個參數(shù):代表接受者 第二個參數(shù):選擇子
(2)具體實現(xiàn)原理:objc_msgSend函數(shù)會依據(jù)接收者與選擇子的類型來調(diào)用適當(dāng)?shù)姆椒?
第一步:先在接受者所屬的類中搜尋其”方法列表”(list of methods)
第二步:若是找不到,會沿著繼承體系繼續(xù)向上查找
第三步:如果還找不到會執(zhí)行”消息轉(zhuǎn)發(fā)”操作.
下次調(diào)用:objc_msgSend會將匹配結(jié)果緩存在”快速映射表中”(每個類都有這樣的一快緩存).
(3):特殊情況下消息調(diào)用需要的函數(shù)補(bǔ)充
第一種:objc_msgSend_stret:如果待發(fā)送的消息返回結(jié)構(gòu)體.(cpu的寄存器能夠容納這個返回體,才會用此函數(shù)).
第二種:objc_msgSend_fpret:消息返回的是浮點數(shù)(這個函數(shù)是為了處理x86等架構(gòu)cpu中某些奇怪的狀況,不懂......)
第三種:objc_msgSend_super:給超類發(fā)消息,例如[super message:parameter],
要點:
(1):消息由接收者,選擇子及參數(shù)構(gòu)成.給某個對象”發(fā)送消息”也就是相當(dāng)于在該對象上”調(diào)用方法”(call a method)
(2):發(fā)給某個對象的全部消息都要由”動態(tài)消息派發(fā)系統(tǒng)”來處理,該系統(tǒng)會查出對應(yīng)的方法,并執(zhí)行方法.
12:理解消息轉(zhuǎn)發(fā)機(jī)制
(1)當(dāng)對象接收到無法解讀的消息后,就會啟動”消息轉(zhuǎn)發(fā)”機(jī)制.
(2)消息轉(zhuǎn)發(fā)分為;兩個階段
第一階段: 先征詢接受者,所屬類看其是否能動態(tài)的添加方法,已處理這個未知的選擇子,這叫做”動態(tài)解析”;
(1):+(BOOL)resolveInstanceMethod:(SEL)select(添加處理未知選擇子的方法)
(2):- (id)forwardingTargetForSelector:(SEL)Selector(備援接收者處理的方法)
第二階段:完整的消息轉(zhuǎn)發(fā)機(jī)制
- (void)forwardInvocation:(NSInvocation*)invocation
要點:
1:若對象無法響應(yīng)某個選擇子,則進(jìn)入消息轉(zhuǎn)發(fā)流程
2:通過運(yùn)行期的動態(tài)方法解析功能,我們可以在需要用到某個方法時在將其加入類中
3:對象可以把其無法解讀的某些選擇子轉(zhuǎn)交給其他對象處理
4:經(jīng)過上述兩步之后,如果還是沒辦法處理選擇子,那就啟動完整的消息轉(zhuǎn)發(fā)機(jī)制
第13條:用”方法調(diào)配技術(shù)”調(diào)試”黑盒方法”
(1):void method_exchangeImplementations(Method m1, Method m2)//交換兩個方法
(2):Method class_getInstanceMethod(Class aClass, SEL aSelector)//此函數(shù)的兩個參數(shù)表示待交換的兩個方法實現(xiàn),
總結(jié):”方法調(diào)配技術(shù)”主要作用是可以為那些”完全不知道其具體實現(xiàn)的”黑盒方法增加日志記錄功能,有助于調(diào)試.
要點:
1:在運(yùn)行期,可以向類中新增或替換選擇子所對應(yīng)的方法實現(xiàn)
2:使用另一份實現(xiàn)來替換原有的方法實現(xiàn),這道工序叫做”方法調(diào)配”開發(fā)者常用此技術(shù)向原有的實現(xiàn)添加新功能
3:一般來說,只有調(diào)試程序的是時候才需要在運(yùn)行期修改方法實現(xiàn),這種方法不宜濫用.?
第14條:理解”類對象”的用意
(1):”在運(yùn)行期檢視對象類型”這一操作叫做”類型信息查詢”
(2):”類對象”:類是一個對象是Class類型的對象簡稱類對象,一個任意的類型全陨,表示一個Objective-C類瑟幕,類名就代表著類對象,每個類只有一個類對象狞玛。
要點:
1:每個實例都有一個指向Class對象的指針(isa),用以表明其類型,而這些Class對象則構(gòu)成了類的繼承體系
2:如果對象類型無法在編譯器確定,那么就應(yīng)該使用類型信息查詢方法來探知
3:盡量使用類型信息查詢方法來確定對象類型,而不要直接比較類對象,因為某些對象可能實現(xiàn)消息轉(zhuǎn)發(fā)功能.
第15條:用前綴避免命名空間沖突
要點:
1.選擇與你的公司,應(yīng)用程序或二者皆有關(guān)聯(lián)之名稱作為類名的前綴,并在所有代碼中均使用這一前綴
2:若自己所開發(fā)的程序庫中用到了第三方庫,則應(yīng)為其中的名稱加上前綴
第16條:提供”全能初始化方法”
(1)全能初始化方法:可以為對象提供必要信息以便其能完成工作的初始化方法.(例如:UITableViewCell).
要點:
1:在類中提供一個全能初始化方法,并于文檔里指明.其他初始化方法均應(yīng)調(diào)用此方法
2:若全能初始化方法與超類不同,則需覆寫超類中的對應(yīng)方法
3:如果超類的初始化方法不適用于子類,那么應(yīng)該覆寫這個超類方法,并在其中拋出異常.
第17條:實現(xiàn)description方法
要點:
1:實現(xiàn)description方法返回一個有意義的字符串,用以描述該實例.
2:若想在調(diào)試時打印出更詳盡的對象描述信息,則應(yīng)實現(xiàn)debugDescription方法
第18條:盡量使用不可變對象
要點:
1:盡量創(chuàng)建不可變的對象
2:若某屬性僅可于對象內(nèi)部修改,則在”class-continuation分類”中將其由readonly屬性擴(kuò)展為readwrite屬性.
3:不要把可變的collection作為屬性公開,而應(yīng)提供相關(guān)方法,以此修改對象中的可變collection.
第19條:使用清晰而協(xié)調(diào)的命名方式
要點
1:起名時應(yīng)該遵從標(biāo)準(zhǔn)的Objective-C命名規(guī)范,這樣創(chuàng)建出來的接口更容易為開發(fā)者所理解
//(例如:方法與變量名使用”駝峰式大小寫命名法”首字母小寫,類名首字母大寫)
2:方法名要言簡意賅,從左至右讀起來像個日常用的句子才好
3:方法名里不要使用縮略后的類型名稱
4:給方法起名時的第一要務(wù)就是確保其風(fēng)格與自己的代碼或有所集成的框架相符
第20條:為私有方法名加前綴
要點:
1:給私有方法的名稱加上前綴,這樣可以很容易地將其同公共方法區(qū)分開
2:不要單用一個下劃線做私有方法的前綴,應(yīng)為這種做法是預(yù)留給蘋果公司用的