Effective Objective-C 2.0 讀書筆記
最近這本書的1刷已經結束了挖胃,然后回過頭來看首先是覺得理解的不夠深入,其次是拓展的不夠寬泛圆丹,所以總結一下郊丛,把核心的東西抽出來便于理解界逛。
1刷是電子書昆稿,刷到末期的時候,直接買了實體書息拜,二刷還是看實體書吧溉潭。
Tip:50 構建緩存時選用NSCache而非NSDictionary
應用場景:下載圖片的后,把內存中的圖片保留下來少欺,以便稍后再用喳瓣。
NSCache的優(yōu)點:
- 系統(tǒng)發(fā)出低內存通知的時候,依據最久未使用(LRU)自動刪減存儲在其中的對象赞别。
- 是線程安全的畏陕,
- 通過改變NSCache屬性中的緩存對象的個數,以及指定緩存空間的大小(開銷)仿滔,當對象總數或者總開銷超過上限的時候緩存就可能會刪除其中的對象惠毁。
NSPurgeableData:
適用范圍解讀
如果某個對象所占的內存可以隨時丟棄,就可以用這個崎页。
也就是說鞠绰,這個類可以把對象標記為<必要時可以丟棄自己所占的內存>
實現原理
實現了NSDiscardableContent協議,這個協議的作用是讓實現該協議所定義的接口
的對象的內存能夠根據需要隨時丟棄实昨。
使用方法
//需要訪問的時候洞豁,調用如下方法,告訴其還不應該丟棄自己所占的內存
[cacheData beginContentAccess];
//使用完之后荒给,調用如下方法,告訴其必要的時候可以丟棄內存
[cacheData endContentAccess];
/*類似引用計數成對出現刁卜,創(chuàng)建NSPurgeableData的操作也會被視為'引用計數+1'*/
Tip:51 精簡initialize 與 load 的實現代碼
首先這兩個方法是屬于NSObject的志电,可以用來實現初始化操作。
load
調用時機:當類和分類加入運行期系統(tǒng)的時候蛔趴√袅荆【程序會阻塞等所有類load執(zhí)行完才繼續(xù)】
執(zhí)行順序:在執(zhí)行子類之前,先執(zhí)行超類的Load方法,如果有其他依賴庫鱼蝉,那他們的load方法也會執(zhí)行(無法判斷類的載入順序)
特點:不遵循繼承規(guī)則洒嗤。就是說超類實現load方法,子類如果沒有實現load魁亦,系統(tǒng)就不會調用load方法渔隶。類的load要比分類的load先執(zhí)行。
注意事項:程序在執(zhí)行l(wèi)oad方法時都會阻塞洁奈,【不要】在load中執(zhí)行任何的任務间唉。
用途:【調試】,在分類中編寫次方法利术,判斷分類是否正確載入系統(tǒng)呈野。
initlalize
調用時機:程序首次用該類之前調用,只調用一次印叁。不要手動調用(它是由運行期系統(tǒng)調用的)
執(zhí)行順序:執(zhí)行的時候被冒,運行期系統(tǒng)處于正常狀態(tài)(應該講的是所有類都已經加載到運行期系統(tǒng)中),然后可以在其中安全的調用任意類的任意方法轮蜕。
安全性:initlalize是線程安全的姆打。執(zhí)行它的時候,其他想要操作initlalize所在類的其他線程都會阻塞等其initlalize執(zhí)行完肠虽。
特點:遵循繼承規(guī)則幔戏,子類會實現父類的initlalize方法。
總結
- 初始化方法里面僅僅適合設置一些狀態(tài)税课,不適合執(zhí)行復雜&加鎖的任務闲延。
- 初始化類的線程是隨機的。當時UI線程時韩玩,初始化期間就會一直阻塞導致應用程序無響應垒玲。
- 無法控制類的初始化時機,也不能令初始化依賴特定的時間點找颓。(萬一運行期系統(tǒng)略微調整合愈,那代碼就失效了)
- 當在初始化方法中(直接或間接)使用到其他類的時候,其他類的initlalize方法中需要用到本類的數據击狮,但是本類的initlalize方法還沒運行完畢佛析,數據可能還沒準備好。
應用
initlalize方法只應該用來設置內部數據彪蓬。
比如說某個全局狀態(tài)無法在編譯期間初始化寸莫。
point:整數可以在編譯期定義,可變數組對象不可以(NSString是可以的)档冬,所以創(chuàng)建期間必須先激活運行期系統(tǒng)膘茎。也就是說讓運行期系統(tǒng)處于【安全期狀態(tài)】
所以可以在initlalize方法中初始化全局的可變數組桃纯,代碼如下
static NSMutableArray *kSomeObjects;
@implementation MyClass
+ (void)initlalize{
//只在當前類初始化,因為initlalize遵循繼承規(guī)則披坏,會被子類調用态坦,所以要加個判斷,讓代碼在本類執(zhí)行棒拂。
if(self == [MyClass class]){
kSomeObjects = [NSMutableArray new];
}
}
Tip:52 別忘了NSTimer會保留其目標對象伞梯。
基礎知識:
- 計時器要和RunLoop相關聯,Runloop到了設定的時間會出發(fā)任務着茸。
- NSTimer會保留其目標對象壮锻,等到自身實現的時候再釋放。
- 一次性的定時器任務結束的時候失效涮阔,重復執(zhí)行的要手動調用invalidate方法使其失效猜绣。
出現保留環(huán)的情況:當沒有顯示調用invalidate方法時,就把使用定時器的類釋放了敬特。這時候NSTimer作為所在類的實例對象掰邢,會被類強引用。而且本類作為NSTimer的target也會被NSTimer強引用伟阔。因此出現循環(huán)引用的情況辣之。
解決方案:為NSTimer添加一個類方法,通過Block創(chuàng)建NSTimer對象皱炉。
userInfo中可以存儲任意類型怀估,因為我們要在回調方法中調用block,但是分類不容易添加屬性合搅,所以就把block拷貝后放到userInfo中多搀,然后在回調方法的參數中取出block來調用。
新的方式:對于調用此方法創(chuàng)建的NSTimer的時候灾部,就可以通過傳入weakSelf 的方式康铭,來打破block的循環(huán)引用了。
Q&A
Q:分類中赌髓,block方式創(chuàng)建NSTimer的方法體中不是會強引用NSTimer類對象么从藤?
A:NSTimer類對象是個單例,計時器是否會保留它都無所謂锁蠕。因為類對象無需回收夷野。