第一次閱讀《Effective Objective-C 2.0》這本書是在15年责嚷,這些年過去回過頭去看箕慧,當年那些經(jīng)驗還是一點都不過時亦渗,有些細節(jié)點還是值得反復強調(diào)又兵。我在這里列舉一些大家可能平時不大會留意的地方。
-- 2019-04-12 00:39 來自StrongX的博客
通過上圖我們知道OC變量指針保存在棧中枫笛,而實際內(nèi)容則是保存在堆中吨灭,這里我們就需要注意懸掛指針的產(chǎn)生,懸掛指針難以調(diào)試刑巧,而且經(jīng)常造成的現(xiàn)象就是一會取值正確喧兄,一會取值不正確。這是由于堆中的內(nèi)容已經(jīng)被標記為釋放啊楚,而實際上內(nèi)存并沒有被釋放吠冤,能否正確取到值取決于這一片內(nèi)存是否被重寫,產(chǎn)生懸掛指針是非常危險的恭理。
- 常量一定要同時使用
static
和const
來修飾拯辙。const
表示該變量不可修改,若是修改由const修飾的變量編譯器就會報錯颜价。而static
表示變量僅在定義此變量的編譯單元中可見薄风。
而實際上我在之前老的項目的確見到過沒有遵循這一準則的情況,沒有同時使用static
和const
同時來修飾一個變量拍嵌,而僅僅使用了const
來做修飾。如果不使用static
來修飾變量循诉,那么編譯器就會對此變量添加一個“外部符號”横辆。那么此時你如果同時在兩個文件中定義了相同的變量名,那么編譯器就會報錯:
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
當然編譯器會告訴在哪些文件中那個變量發(fā)生了重復定義。所以我們在定義常量的時候一定要同時使用static
和const
來進行定義狈蚤,因為發(fā)生重名情況并不罕見困肩。
-
readonly
和readwrite
讀寫權(quán)限:
我們經(jīng)常有這樣的場景:我們需要提供變量對外可讀,但是在類實現(xiàn)中可以去修改脆侮,所以我們在 .h
文件中定義變量為readonly
:
@property (nonatomic, strong,readonly) NSString *name;
然而這個時候我們無法.m
文件中進行修改锌畸,當你試圖去修改一個由readonly
定義的變量時,編譯器會發(fā)出錯誤:
Assignment to readonly property
那么這個時候我們可以在分類
中同時將變量定義為readwrite
(不了解分類概念的同學靖避,可以自行去了解下)
@property (nonatomic, strong, readwrite) NSString *name;
- 蘋果的框架中使用了大量的類族潭枣,比如
NSArray
、NSNumber
······我們需要注意類族隱藏了大量的子類幻捏,暴露給我們的只是一個抽象類盆犁,我們使用抽象類初始化方法返回給我的并不是抽象類本身,注意點: - 在創(chuàng)建類族的子類的時候需要額外注意篡九,當我們將一個抽象類作為父類的時候一定要實現(xiàn)它所有的初始化方法和原始方法谐岁。
- 抽象類本身自己不提供存儲,存儲是由自己實現(xiàn)的榛臼,所以你繼承自抽象類的子類也一定要自己實現(xiàn)存儲伊佃,(比如給他一個屬性
NSArray
),筆者不建議去創(chuàng)建一個抽象類的子類沛善,你可以使用擴展的方式去代替航揉。當然你自己在設計自己的架構(gòu)的時候,類族是一種很值得考慮的方式(如果有一大堆子類的時候)路呜。 - 以下判斷永遠不會為真:
id maybeAnArray = /* ... */;
if ([maybeAnArray class] == [NSArray class]) {
// Will never be hit
}
我們都知道使用
NSCache
來實現(xiàn)緩存迷捧,從使用方法來看和使用NSDictionary
類似,那么我們?yōu)槭裁床恢苯邮褂?code>NSDictionary胀葱?使用NSCache
有幾個好處:NSCache
實現(xiàn)了自動刪減緩存漠秋,也就是說當系統(tǒng)發(fā)出低內(nèi)存警告的時候,NSCache
會自動去釋放最久未使用的對象抵屿,并且你還可以對NSCache
設置最大內(nèi)存等相關(guān)設置庆锦。當然這些功能,你使用NSDictionary
添加些額外參數(shù)也能夠?qū)崿F(xiàn)轧葛,不過老實說你花了大功夫?qū)崿F(xiàn)你的緩存機制后可能還真的不一定比NSCache
好用搂抒,這個讓我想到某個很出名的圖片加載框架~~~~在某些情況下我們將某個對象最為字典的key(可能絕大多數(shù)情況下是字符串),蘋果的代碼中也有很多這樣的對象尿扯,比如weak的弱引用表......當我們將對象作為字典的key時求晶,對象必須只是拷貝,也就是我們需要實現(xiàn)
NSCopying
協(xié)議衷笋,然而NSCache
不需要芳杏,你可以將任意OC對象最為NSCache
的鍵值。NSCache
默認是線程安全,線程安全對緩存來說是非常重要的爵赵。如果你使用NSDictionary
那么你必須手動添加很多l(xiāng)ock等操作吝秕,lock這個東西加好了沒問題,一不留神發(fā)生死鎖是很常見的空幻。
- 我們知道使用
NSTimer
的時候有很多需要注意點烁峭,如:
1、未銷毀計時器而導致發(fā)生內(nèi)存泄漏秕铛。
2约郁、由于runloop Mode而產(chǎn)生的各種問題
······
筆者之前一直使用GCD Source來替代NSTimer,不過在書中提到了另外一種方式如捅,筆者認為很新穎棍现,之前從未想到過豹缀。
上面這段代碼完美解決了由于計時器持有self
渤弛,self
又持有計時器而導致計時器若是不銷毀就會發(fā)生內(nèi)存泄漏的問題,計時器不再持有self
,在iOS 10以后NSTimer
開放給我們的接口中出現(xiàn)了這么一個方法:
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block;
使用此方法創(chuàng)建的計時器同樣不會造成“保留環(huán)”茎刚,估計實現(xiàn)方式和上面貼的那段代碼估計原理是類似的悲关。
先寫這么多谎僻,下回再寫,晚安寓辱。