ARC機制
以往的OBJC是通過程序員手動地管理對象的釋放。ARC(Automatic Reference Counting)自動引用計數(shù),現(xiàn)在是OBJC的默認(rèn)內(nèi)存管理機制,針對堆上的對象,由編譯器自動生成操作引用計數(shù)的指令(retain,release)來管理對象的釋放。
管理的對象
受ARC管理 | 不受ARC管理 |
---|---|
OC對象指針 | 值類型(基本類型,struct) |
Block指針 | 其他方式分配的資源(c語言的malloc) |
使用attribute((NSObject))定義的typedef | 非內(nèi)存資源 |
管理的方式
//新創(chuàng)建一個引用類型的對象,這個對象的引用計數(shù)初始為1;
NSString *name = [[NSString alloc] initWithString:@"Mono"];
//將對象引用賦值給其它變量或者常量,引用計數(shù)+1;
NSString *otherName = name;
//或者將將該對象引用賦值給其它對象的屬性或?qū)嵗兞浚糜嫈?shù)+1;
person.name = name;
//將對象傳入函數(shù)參數(shù),或者返回值,引用計數(shù)+1
print(name);//函數(shù)結(jié)束后,參數(shù)或者局部變量離開函數(shù),該對象的引用計數(shù)-1;
//將對象加入集合之中,引用計數(shù)+1;
[array addObject];
//將變量或者常量,或者屬性賦值為nil或者其他值,引用計數(shù)-1;
otherName = nil; or otherName = @"Other Name";
person.name = nil;
//實例變量和屬性所在的對象唄釋放,該對象引用計數(shù)-1;
[person release];
//將對象從集合中移除的時候,該對象的引用計數(shù)-1;
[array removeObject:name];
//當(dāng)該對象的引用計數(shù)變?yōu)?的時候,內(nèi)存自動被釋放。
自動釋放池(Autorelease Pool)
如果對象頻繁的進行釋放和分配,那么會造成瑣碎的內(nèi)存管理負(fù)擔(dān)。autorelease可以講release的調(diào)用延遲到自動釋放池被釋放時。
當(dāng)自動釋放池結(jié)束時,所有接受autorelease消息的對象都將被立即釋放(對象被發(fā)送一條release消息);
AppKit和UIKit框架在處理每一次事件循環(huán)迭代時,都會講其放入一個Autorelease Pool中,大多數(shù)情況無須程序員干預(yù)。
需要手動管理Autorelease Pool的情況
1.當(dāng)編寫的程序不是基于UI框架,而是命令行程序時。
2.如果在循環(huán)中創(chuàng)建大量臨時對象,需要更早地釋放,避免臨時對象聚集導(dǎo)致內(nèi)存峰值過大。
3.在主線程之外創(chuàng)建新的線程,在新線程開始執(zhí)行處,需要創(chuàng)建自己的Autorelease Pool。
4.嵌套使用Autorelease Pool的時候。
協(xié)議 Protocol
類型的合同約定,只描述外部接口,不提供具體的實現(xiàn)。
協(xié)議中無法包含實例變量,但可以包含以下的成員:
屬性 (本質(zhì)上是訪問器方法,編譯器不會合成實例變量)
實例方法
類方法
初始化器,析構(gòu)器(不常用)
使用協(xié)議
1.一個類遵守協(xié)議,需實現(xiàn)該協(xié)議約定的所有@required的成員,即必須要實現(xiàn)的成員。
協(xié)議中的屬性必須在實現(xiàn)類的.h接口文件中聲明(編譯器合成實例變量)
2.協(xié)議本質(zhì)上是一種類型,可以作為聲明類型,但是不能創(chuàng)建實例。
3.可以使用conformsToProtocl:檢查是否實現(xiàn)了協(xié)議。
4.編譯警告:1)未實現(xiàn)必選方法。2)協(xié)議類型變量被賦值為非協(xié)議類型變量。運行會出錯。
協(xié)議的繼承
一個協(xié)議可以繼承一個或者多個協(xié)議。
實現(xiàn)子協(xié)議的類型,同時也要實現(xiàn)父協(xié)議中必須是實現(xiàn)的成員。
協(xié)議的組合
一個類可以同時實現(xiàn)多個協(xié)議,protocal<A,B,C....>來組合多個協(xié)議
實現(xiàn)組合協(xié)議的類型,必須實現(xiàn)組合協(xié)議中的每一個協(xié)議
協(xié)議中的可選
協(xié)議中使用關(guān)鍵字@optional定義的成員是可以選擇不必實現(xiàn)的。
常用的協(xié)議
名稱 | 描述 |
---|---|
NSObject | 包含對象的常用操作,相等、字符串表示、哈希。 |
NSCopying | 支持復(fù)制的類型必須遵守該協(xié)議。 |
NSMutableCopying | 在NSCopying協(xié)議的基礎(chǔ)上,支持復(fù)制數(shù)據(jù)的可變性。 |
NSFastEnumeration | 實現(xiàn)快速枚舉for-in的類型采用 |
NSCoding | 支持將對象圖進行編碼或解碼以支持對象的序列化 |
類別 Categroy
可增加 | 不可增加 |
---|---|
類方法 | 屬性 |
實例方法 | 實例變量 |
重寫父類方法 | 已存在的同名方法 |
在沒有源代碼的情況下,基于某些場合的需要,為一個類增加功能。
可增加 | 不可增加 |
---|---|
類方法 | 屬性 |
實例方法 | 實例變量 |
重寫父類方法 | 已存在的同名方法 |
命名規(guī)范
文件名:類名+擴展方法,如:Person+Sport.h/m
類別的使用
場景
1.適合在沒有源代碼的情況下,想已經(jīng)封裝的類中添加方法。
2.為一個類在某些特殊場景下增加功能。
3.對于復(fù)雜的大型文件分割實現(xiàn)。
4.可以通過類別重寫現(xiàn)有方法,但一般不推薦,這樣會導(dǎo)致無法調(diào)用被擴展的類的初始方法,只能訪問重寫過的方法。
添加類別的對象
1.自己創(chuàng)建的類。
2.系統(tǒng)的類。
3.第三方庫。
類別限制
1.類別不能在擴展類中添加任何成員變量。
2.重寫現(xiàn)有方法時,無法調(diào)用原始現(xiàn)有對象方法。
3.若兩個類別都定義了一個相同類的相同方法,運行時實際無法確定調(diào)用哪一個。
擴展 Extension
擴展支持在編譯時,在有類的源代碼的前提下,向類添加功能。可看做是匿名的類別。
接口在.m文件中的@implementation前聲明,實現(xiàn)代碼在@implementation 內(nèi)實現(xiàn)。
擴展支持添加以下成員:
1.屬性。
2.實例成員。
3.類方法。
4.實例方法。
5.改寫屬性的讀寫屬性。
擴展的使用
擴展實現(xiàn)的成員只能在。m文件內(nèi)部訪問,類外無法直接往訪問。
擴展的主要用途在于信息隱藏,隱藏一些外部無須訪問、而內(nèi)部實現(xiàn)又需要使用的屬性、方法:
1.類的主要接口用于“對類以外公開”
2.類的擴展接口用于“對類內(nèi)可見”