Effective Objective-C 2.0讀書筆記
第一章
- 消息結(jié)構(gòu)和函數(shù)調(diào)用的區(qū)別:消息調(diào)用的語言商玫,其運(yùn)行時(shí)所執(zhí)行的代碼由運(yùn)行環(huán)境來決定;函數(shù)調(diào)用則有編譯器決定渤早。
第二章
- 在類的頭文件中盡量少引用其他頭文件靠粪,用@class字段聊疲,減少編譯時(shí)間
第三章
- 多用@()來創(chuàng)建字面量
第四章
用#define會(huì)把所有的做替換尖奔,并且不會(huì)做類型判斷搭儒,也不會(huì)有同名警告。#define kTimeDuration 0.3
如果只要該編譯單元(.m文件)內(nèi)使用提茁。static const NSInteger kTimeDuration = 0.3;
如果要給外部可用淹禾,那么就這樣,命名要謹(jǐn)慎:
(.h)extern NSString * const EOCStringConstant;
(.m) NSString * const EOCStringConstant = @"Value";
第五章
用NS_ENUM和NS_OPTIONS定義的枚舉類型茴扁,并指明期底層數(shù)據(jù)類型铃岔,就能保證是用開發(fā)者選擇的底層數(shù)據(jù)類型來實(shí)現(xiàn),而不會(huì)采用編譯器所選的類型丹弱。
如果想組合多個(gè)選項(xiàng)的枚舉德撬,把值定義為2的冪铲咨,這樣就可以“按位或”起來躲胳。
第六章
- @property的各種語義聲明蜓洪。在使用copy的時(shí)候,會(huì)拷貝一份副本坯苹,如果自己實(shí)現(xiàn)setter方法隆檀,自己要加上copy
第七章
- none
第八章
- 兩個(gè)對象相等,請重寫isEqual:方法
第九章
- 用類簇來屏蔽細(xì)節(jié)(大圖瀏覽器)
第十章
- 關(guān)聯(lián)對象粹湃,具體可見UIAlertView綁定block的demo恐仑,但是建議不要輕易使用該技術(shù)可能導(dǎo)致難以發(fā)現(xiàn)的bug
第十一章
- id returnValue = [someObject messageName:parameter];
其中,someObject叫做“接收者”(receiver)为鳄,messageName叫做“選擇器”(selector), 選擇器和參數(shù)合起來稱為“消息(Message)”
編譯器會(huì)把它轉(zhuǎn)換為如下函數(shù):
id returnValue = objc_msgSend(someObject, @selector(messageName:), parameter);
第十二章
- 消息轉(zhuǎn)發(fā)流程(三部曲):
- 先詢問接受者能否動(dòng)態(tài)添加方法來處理未知的selector(unknown selector)裳仆,這叫“動(dòng)態(tài)方法解析”,會(huì)調(diào)用其所屬類的這個(gè)方法,取決于是類方法還是實(shí)例方法孤钦。此方案常用來實(shí)現(xiàn)@dynamic.
(BOOL)resolveInstanceMethod:(SEL)selector;
(BOOL)resolveClassMethod:(SEL)selector;
- 如果執(zhí)行完第一步?jīng)]有結(jié)束歧斟,那么接受者自己就無法再以動(dòng)態(tài)新增方法的手段來響應(yīng)該消息了。此時(shí)Runtime會(huì)看看有沒有其他的對象來處理這條消息偏形,轉(zhuǎn)發(fā)給其他的接受者來處理.下面的方法如果能找到備胎對象静袖,就把備胎對象返回;如果沒有找到就返回nil俊扭。"備援接收者".模擬多重繼承队橙。
- (id)forwardingTargetForSelector:(SEL)selector;
- 如果沒有備胎,那就把消息有關(guān)的全部細(xì)節(jié)都封裝到NSInvocation對象中萨惑,再給接收者最后一次機(jī)會(huì)來處理捐康。會(huì)啟動(dòng)“完整的消息轉(zhuǎn)發(fā)機(jī)制”。首先創(chuàng)建NSInvocation對象庸蔼,把尚未處理的那條消息有關(guān)的全部細(xì)節(jié)都封于其中吹由,此對象包含選擇器、目標(biāo)(target)及參數(shù)朱嘴。在觸發(fā)NSInvocation對象時(shí)倾鲫,“消息派發(fā)系統(tǒng)(message-dispatch system)”會(huì)親自出馬,把消息指派給目標(biāo)對象:
- (void)forwardInvocation:(NSInvocation *)invocation;
- 如果最后調(diào)用了NSObject類的方法還是搞不定萍嬉,會(huì)繼續(xù)調(diào)用doesNotrecognizeSelector來拋出異常乌昔。
全過程圖示如下:或者見p49
- 具體的@dynamic示例見p48
第十三章
- Method Swizzling,可以給“完全不知道其具體實(shí)現(xiàn)的(completely opaque 完全不透明的)”黑盒方法添加日志記錄功能壤追。不要濫用該方法
第十四章
每個(gè)對象結(jié)構(gòu)體的首個(gè)成員是Class類的變量磕道,該變量定義了對象所屬的類,即“isa”指針行冰。Class對象也被定義為P57的結(jié)構(gòu)體溺蕉,結(jié)構(gòu)體存放類的元數(shù)據(jù)“metadata”伶丐,該結(jié)構(gòu)體的首個(gè)變量也是個(gè)isa指針,說明Class本身也是一個(gè)Objective-C對象疯特。類對象的isa指針指向的類型是另外一個(gè)類哗魂,叫做元類“metaclass”,“類方法”(+號方法)就是定義在metaclass里面的漓雅。
isMemberOfClass判斷對象是否是一個(gè)特定具體類的實(shí)例录别。
isKindOfClass是判斷對象是否為某類或其派生類(子類)的實(shí)例。
第十五章
none
第十六章
none
第十七章
- 重寫description方法邻吞,可以利用NSDictionary的desccription方法來簡化
第十八章
none
第十九章/第二十章/第二十一章
none
第二十二章 copy
- copy和mutableCopy調(diào)用小結(jié)组题,copy返回不可變,mutableCopy返回可變抱冷。
針對不可變對象調(diào)用copy返回該對象本身(舊的)崔列,調(diào)用mutableCopy返回一個(gè)可變對象(新的);
針對可變對象調(diào)用copy返回一個(gè)不可變對象(新的)旺遮,調(diào)用mutableCopy返回另外一個(gè)可變對象(新的)赵讯。
- @property
不可變類型屬性,推薦使用copy趣效,因?yàn)榧僭O(shè)該對象實(shí)際上指向的是一個(gè)mutable的對象瘦癌,mutable對象的改變不會(huì)導(dǎo)致該對象的改變;假設(shè)指向的不是mutable的對象跷敬,那么copy和strong是等價(jià)讯私,都是執(zhí)行一次retain。
可變類型屬性西傀,不能使用copy斤寇,因?yàn)閏opy產(chǎn)生的對象是一個(gè)不可變對象,跟屬性描述是沖突的拥褂。
- 深拷貝和淺拷貝的區(qū)別:
深拷貝:拷貝內(nèi)容娘锁,且產(chǎn)生新對象。新對象計(jì)數(shù)器置為1饺鹃,原對象計(jì)數(shù)器不變莫秆。副本對象改變時(shí)不改變原對象
淺拷貝:拷貝地址,不產(chǎn)生新對象悔详。原對象計(jì)數(shù)器加1.只有一種情況是淺拷貝(不可變對象調(diào)用不可變的copy方法)
第二十三章
none
第二十四章
- 給一個(gè)比較大的類拆分成幾個(gè)功能區(qū)塊的小類镊屎,可以考慮使用分類
第二十五章
- 使用分類時(shí),盡量要添加前綴
第二十六章
- 分類不能添加屬性茄螃,要使用關(guān)聯(lián)對象缝驳,或者@dynamic。所以關(guān)于對象的所有定義都要放在主接口中
第二十七章
看不懂怎么辦
第二十八章
通過協(xié)議來隱藏類名,類似泛型的思想
第二十九章
ARC是把幾乎所有的內(nèi)存管理事宜都交給編譯器來決定用狱,開發(fā)者只需專注業(yè)務(wù)邏輯
Setter方法中运怖,必須先retain新值,release舊值夏伊,然后更新實(shí)例對象摇展。順序很重要否則會(huì)變成懸掛指針
調(diào)用release會(huì)立刻遞減對象的引用計(jì)數(shù),調(diào)用autorelease會(huì)在稍后遞減引用計(jì)數(shù)署海,通常在下一次事件循環(huán)(event loop)時(shí)遞減吗购,不過也有可能執(zhí)行得更早些(34章)
內(nèi)存泄露:沒有正確釋放該釋放的內(nèi)存(已經(jīng)不再使用的內(nèi)存)
第三十章
使用ARC要注意医男,引用計(jì)數(shù)實(shí)際上還是要執(zhí)行的砸狞,只不過保留和釋放操作現(xiàn)在是由ARC自動(dòng)為我們添加,并且ARC添加的是底層的C語言函數(shù)镀梭,如objc_retain刀森。
ARC只負(fù)責(zé)管理Objective-C對象的內(nèi)存,CoreFoundation對象不歸ARC管理报账,開發(fā)者必須適時(shí)調(diào)用CFRetain研底、CFRelease.
第三十一章
- ARC會(huì)通過自動(dòng)生成的.cxx_destruct方法在dealloc中自動(dòng)添加釋放代碼。CoreFoundation對象必須手工釋放透罢。
第三十二章
- none
第三十三章
- 用弱引用避免循環(huán)引用
第三十五章
不是很明白
第三十六章
- 不要使用retainCount
第三十七章榜晦、第三十八章
- 定義block的時(shí)候,他的內(nèi)存區(qū)域是分配在棧上的羽圃。就是說乾胶,塊只在定義它的范圍內(nèi)有效。比如:
void (^block);
if (A) {
block = ^{ NSLog(@"A")};
} else {
block = ^{ NSLog(@"B")};
}
這個(gè)block很可能會(huì)被回收朽寞,因?yàn)橹辉趇f或者else里面有效识窿。
正確的做法:
void (^block);
if (A) {
block = [^{ NSLog(@"A")} copy];
} else {
block = [^{ NSLog(@"B")} copy];
}
- block會(huì)把局部變量捕獲,block會(huì)在
定義時(shí)
就把當(dāng)時(shí)的局部變量值捕獲進(jìn)來脑融;如果想在運(yùn)行時(shí)
再捕獲喻频,就加上__block
第三十九、四十章
none
第四十一章
- 多用派發(fā)隊(duì)列表述同步語義肘迎,比@synchronized和NSLock要好