編寫高質(zhì)量iOS與OS X代碼的52個有效方法

本文授權(quán)轉(zhuǎn)載,作者:千煌89(簡書

本篇是我閱讀《Effective Objective-C 2.0》的摘要與總結(jié)。

一倚喂、熟悉Objective-C

了解Objective-C語言的起源

Objective-C為C語言添加了面向?qū)ο筇匦裕瞧涑bjective-C使用動態(tài)綁定的消息結(jié)構(gòu)菲饼,也就是說,在運(yùn)行時才會檢查對象類型列赎。接收一條消息之后宏悦,究竟應(yīng)執(zhí)行何種代碼,由運(yùn)行環(huán)境而非編譯器來決定包吝。

理解C語言的核心概念有助于寫好Objective-C程序饼煞。尤其要掌握內(nèi)存模型與指針。

在類的頭文件中盡量少引入其他頭文件

除非確有必要诗越,否則不要引入頭文件砖瞧。一般來說,應(yīng)在某個類的頭文件中使用向前聲明(forward declaring)來提及別的類嚷狞,并在實(shí)現(xiàn)文件中引入那些類的頭文件块促。這樣做可以盡量降低類之間的耦合荣堰。

有時無法使用向前聲明,比如要聲明某個類遵循一項(xiàng)協(xié)議褂乍。這種情況下持隧,盡量把“該類遵循某協(xié)議”的這條聲明移至“class-continuation”分類中。如果不行的話逃片,就把協(xié)議單獨(dú)放在一個頭文件中,然后將其引入只酥。

多用literal語法褥实,少用與之等價的方法

比如多用NSArray *array = @[@1,@2];少用NSArray *array = [NSArray arrayWithObjects:@1,@2,nil];

應(yīng)該使用literal語法來創(chuàng)建字符串,數(shù)值裂允,數(shù)組损离,字典。與創(chuàng)建此類對象的常規(guī)方法相比绝编,這么做更加簡明扼要僻澎。

應(yīng)該通過取下標(biāo)操作來訪問數(shù)組下標(biāo)或字典中的鍵所對應(yīng)的元素。

用literal語法創(chuàng)建數(shù)組或字典時十饥,若值中有nil窟勃,則會拋出異常。因此逗堵,務(wù)必確保值里不含nil秉氧。

多用類型常量,少用#define預(yù)處理指令

不要用預(yù)處理指令定義常量蜒秤。這樣定義出來的常量不含類型信息汁咏,編譯器只是會在編譯前據(jù)此執(zhí)行查找與替換操作。即使有人重新定義了常量值作媚,編譯器也不會產(chǎn)生警告信息攘滩,這將導(dǎo)致應(yīng)用程序中的常量值不一致。

在實(shí)現(xiàn)文件中使用static const來定義只在編譯單元內(nèi)可見的常量纸泡。由于此類常量不在全局符號表中漂问,所以無需為其名稱加前綴。

在頭文件中使用extern來聲明全局常量弟灼,并在相關(guān)實(shí)現(xiàn)文件中定義其值级解。這種常量要出現(xiàn)在全局符號表中,所以其名稱要加以區(qū)隔田绑,通常用與之相關(guān)的類名做前綴勤哗。

用枚舉表示狀態(tài)、選項(xiàng)掩驱、狀態(tài)碼

應(yīng)該用枚舉來表示狀態(tài)機(jī)的狀態(tài)芒划、傳遞給方法的選項(xiàng)遺跡狀態(tài)碼等值冬竟,給這些值起個易懂的名字。

如果把傳遞給某個方法的選項(xiàng)表示為枚舉型民逼,而多個選項(xiàng)又可同時使用泵殴,那么就將各選項(xiàng)值定義為2的冪,以便通過按位或者操作將其組合起來拼苍。

用NS_ENUM與NS_OPTIONS宏來定義枚舉類型笑诅,并指明其底層數(shù)據(jù)類型。這樣做可以確保枚舉是用開發(fā)者所選的底層數(shù)據(jù)類型實(shí)現(xiàn)出來的疮鲫,而不會采用編譯器所選的類型吆你。

在處理枚舉類型的switch語句中不要實(shí)現(xiàn)default分支。這樣的話俊犯,加入新枚舉之后妇多,編譯器就會提示開發(fā)者:switch語句并未處理所有的枚舉。

二燕侠、對象者祖、消息、runtime

理解“屬性”這一概念

可以通過@property語法來定義對象中所封裝的數(shù)據(jù)绢彤。

通過“特質(zhì)”來指定存儲數(shù)據(jù)所需的正確語義

在設(shè)置屬性所對應(yīng)的實(shí)例變量時逻恐,一定要遵從該屬性所聲明的語義富弦。

開發(fā)iOS程序時蜡饵,應(yīng)該使用nonatomic屬性精盅,因?yàn)閍tomic屬性會嚴(yán)重影響性能。

在對象內(nèi)部盡量直接訪問實(shí)例變量

在對象內(nèi)部讀取數(shù)據(jù)時奇适,應(yīng)該直接通過實(shí)例變量來讀坟比,而寫入數(shù)據(jù)時,應(yīng)該通過屬性來寫嚷往。

在初始化方法及dealloc方法中葛账,總是應(yīng)該直接通過實(shí)例變量來讀寫數(shù)據(jù)。

有時會使用惰性初始化技術(shù)配置某份數(shù)據(jù)皮仁,這種情況下籍琳,需要通過屬性來讀取數(shù)據(jù)。

理解“對象等同性”這一概念

若想檢測對象的等同性贷祈,請?zhí)峁癷sEqual:”與hash方法趋急。

相同的對象必須具有相同的hash碼,但是兩個hash碼相同的對象卻未必相同势誊。

不要盲目的逐個監(jiān)測每條屬性呜达,而是應(yīng)該依照具體需求來制定檢測方案。

編寫hash方法時粟耻,應(yīng)該使用計(jì)算速度快而且哈希碼碰撞幾率低的算法查近。

以“類族模式”隱藏實(shí)現(xiàn)細(xì)節(jié)

類族模式可以把實(shí)現(xiàn)細(xì)節(jié)隱藏在一套簡單的公共接口后面眉踱。

系統(tǒng)框架中經(jīng)常使用類族。

從類族的公共抽象基類中繼承子類時要當(dāng)心霜威,若有開發(fā)文檔谈喳,則應(yīng)首先閱讀。

在既有類中戈泼,使用關(guān)聯(lián)對象(Associated Object)存放自定義數(shù)據(jù)

可以通過“關(guān)聯(lián)對象”機(jī)制來把兩個對象連起來婿禽。

定義關(guān)聯(lián)對象時可指定內(nèi)存管理語義,用以模仿定義屬性時所采用的“擁有關(guān)系”與“非擁有關(guān)系”大猛。

只有在其他做法不可行時才應(yīng)選用關(guān)聯(lián)對象谈宛,因?yàn)檫@種做法通常會引入難于查找的bug。

理解objc_msgSend的作用

消息由接受者胎署,selector及參數(shù)構(gòu)成。給某對象“發(fā)送消息”也就相當(dāng)于在該對象上調(diào)用方法窑滞。

發(fā)給某對象的全部消息都要由“動態(tài)消息派發(fā)系統(tǒng)”來處理琼牧,該系統(tǒng)會查出對應(yīng)的方法,并執(zhí)行其代碼哀卫。

理解消息轉(zhuǎn)發(fā)機(jī)制

若對象無法響應(yīng)某個selector巨坊,則進(jìn)入消息轉(zhuǎn)發(fā)流程。

通過運(yùn)行期的動態(tài)方法解析功能此改,我們可以在需要用到某個方法時再將其加入類中趾撵。

對象可以將其無法解讀的某些selector轉(zhuǎn)交給其他對象處理。

經(jīng)過上述兩步后共啃,如果還是沒辦法處理selector占调,那就啟動完整的消息轉(zhuǎn)發(fā)機(jī)制。

用method swizzling調(diào)試黑盒方法

在runtime中移剪,可以向類中新增或替換selector所對應(yīng)的方法實(shí)現(xiàn)究珊。

使用另一份實(shí)現(xiàn)來替換原有的方法實(shí)現(xiàn),這道工序叫做method swizzling纵苛,開發(fā)者常用此技術(shù)向原有視線中添加功能剿涮。

一般來說,只有調(diào)試程序的時候才需要在runtime中修改方法實(shí)現(xiàn)攻人,這種做法不宜濫用取试。

理解“類對象”的用意

每個實(shí)例都有一個指向Class對象的指針,用以表明其類型怀吻,而這些Class對象則構(gòu)成了累的繼承體系瞬浓。

如果對象類型無法在編譯期確定,那么就應(yīng)該使用類型信息查詢方法來探知烙博。

盡量使用類型信息查詢方法來確定對象類型瑟蜈,而不要直接比較類對象烟逊,因?yàn)槟承ο罂赡軐?shí)現(xiàn)了消息轉(zhuǎn)發(fā)功能。

三铺根、接口與API設(shè)計(jì)

用前綴避免命名空間沖突

選擇與你公司宪躯、應(yīng)用程序或者二者皆有關(guān)聯(lián)之名稱作為類名的前綴,并在所有代碼中均使用這一前綴位迂。

若自己所開發(fā)的程序庫中用到了第三方庫访雪,則應(yīng)為其中的名稱加上前綴。

Apple宣稱保留使用所有兩字母前綴的權(quán)利掂林,所以自己所選用的前綴最好是三字母的臣缀。

提供“全能初始化方法”

在類中提供一個全能初始化方法,并于文檔里指明泻帮。其它初始化方法均應(yīng)調(diào)用此方法精置。

若全能初始化方法與超類不同,則需覆寫超類中對應(yīng)方法锣杂。

如果超類的初始化方法并不適用于子類脂倦,那么應(yīng)該覆寫這個超類方法,并在其中拋出異常元莫。

實(shí)現(xiàn)description方法

實(shí)現(xiàn)description方法返回一個有意義的字符串赖阻,用以描述該實(shí)例。

若想在調(diào)試時打印出更詳盡的對象描述信息踱蠢,則應(yīng)該實(shí)現(xiàn)debugDescription方法火欧。

盡量使用不可變對象

盡量創(chuàng)建不可變的對象。

若某屬性僅可于對象內(nèi)部修改茎截,則在“class-continuation分類”中將其由readonly屬性擴(kuò)展為readwrite屬性苇侵。

不要把可變的collection作為屬性公開,而應(yīng)提供相關(guān)方法稼虎,一次修改對象中的可變collection衅檀。

使用清晰而協(xié)調(diào)的命名方式

起名時應(yīng)遵從標(biāo)準(zhǔn)的Objective-C命名規(guī)范,這樣創(chuàng)建出來的接口更容易為開發(fā)者所理解霎俩。

方法名要言簡意賅哀军,從左至右讀起來要像個日常用語中的句子才好。

方法名利不要使用縮略后的類型名稱打却。

給方法嗎起名時的第一要務(wù)就是確保其風(fēng)格與你自己的代碼或所要集成的框架相符杉适。

為私有方法名加前綴

給私有方法的名稱加上前綴,這樣可以很容易的將其通公共方法區(qū)分開柳击。

不要單用一個下劃線做私有方法的前綴猿推,因?yàn)檫@種做法的預(yù)留給蘋果公司用的。

理解Objective-C錯誤模型

只有發(fā)生了可使整個應(yīng)用程序崩潰的嚴(yán)重錯誤時,才使用異常蹬叭。

在錯誤不那么嚴(yán)重的情況下藕咏,可以指派委托方法來處理錯誤,也可把錯誤信息放在NSError對象里秽五,經(jīng)由輸出參數(shù)返回給調(diào)用者孽查。

理解NSCopying協(xié)議

若想令自己所寫的對象具有拷貝功能,則需實(shí)現(xiàn)NSCopying協(xié)議坦喘。

如果自定義的對象分為可變版本與不可變版本盲再,那么就要同時實(shí)現(xiàn)NSCopying與NSMutableCopying協(xié)議。

復(fù)制對象時需決定采用淺拷貝還是深拷貝瓣铣,一般情況下應(yīng)該盡量執(zhí)行淺拷貝答朋。

如果你所寫的對象需要深拷貝,那么可考慮新增一個專門執(zhí)行深拷貝的方法棠笑。

四梦碗、協(xié)議與分類

通過委托與數(shù)據(jù)源協(xié)議進(jìn)行對象間通信

委托模式為對象提供了一套接口,使其可由此將相關(guān)事件告知其他對象蓖救。

將委托對象應(yīng)該支持的接口定義成協(xié)議叉弦,在協(xié)議中把可能需要吃力的事件定義成方法。

當(dāng)某對象需要從另外一個對象中獲取數(shù)據(jù)時藻糖,可使用委托模式。在這種情況下库车,該模式亦稱數(shù)據(jù)源協(xié)議巨柒。

若有必要,可實(shí)現(xiàn)含有位段的結(jié)構(gòu)體柠衍,將委托對象是否能響應(yīng)相關(guān)協(xié)議方法這一信息緩存至其中洋满。

將類的實(shí)現(xiàn)代碼分散到便于管理的數(shù)個分類之中

使用分類機(jī)制把類的實(shí)現(xiàn)代碼劃分成易于管理的小塊。

將應(yīng)該視為私有的方法歸入名叫Private的分類中珍坊,以隱藏實(shí)現(xiàn)細(xì)節(jié)牺勾。

總是為第三方類的分類名稱加前綴

向第三方類中添加分類時,總應(yīng)給其名稱加上你專用的前綴阵漏。

向第三方類中添加分類時驻民,總應(yīng)給其中的方法名加上你專用的前綴。

勿在分類中聲明屬性

把封裝數(shù)據(jù)所用的全部屬性都定義在主接口里履怯。

在class-continuation分類之外的其他分類中回还,可以定義存取方法,但盡量不要定義屬性叹洲。

使用class-continuation分類隱藏實(shí)現(xiàn)細(xì)節(jié)

通過class-continuation分類向類中新增實(shí)例變量柠硕。

如果某屬性在主接口中聲明為只讀,而類的內(nèi)部又要用設(shè)置方法修改此屬性运提,那么就在class-continuation分類中將其擴(kuò)展為可讀寫蝗柔。

把私有方法的原型聲明在class-continuation分類里面闻葵。

若想使類遵循的協(xié)議不為人所知,則可于class-continuation分類中聲明癣丧。

通過協(xié)議提供匿名對象

協(xié)議可在某種程度上提供匿名類型槽畔。具體的對象類型可以淡化成遵從某些一的id類型,協(xié)議里規(guī)定了對象所應(yīng)實(shí)現(xiàn)的方法坎缭。

使用匿名對象來隱藏類型名稱或類名竟痰。

如果具體類型不重要,重要的是對象能夠響應(yīng)(定義在協(xié)議里的)特定方法掏呼,那么可使用匿名對象來表示坏快。

五、內(nèi)存管理

理解引用計(jì)數(shù)

引用計(jì)數(shù)機(jī)制通過可以遞增遞減的計(jì)數(shù)器來管理內(nèi)存憎夷。對象創(chuàng)建好后莽鸿,其保留計(jì)數(shù)至少為1.若保留計(jì)數(shù)為正,則對象繼續(xù)存活拾给。當(dāng)保留計(jì)數(shù)降為0時祥得,對象就被銷毀了。

在對象生命期中蒋得,其余對象通過引用來保留或釋放此對象级及。保留與釋放操作分別會遞增及遞減保留計(jì)數(shù)。

以ARC簡化引用計(jì)數(shù)

在ARC之后额衙,程序員就無須擔(dān)心內(nèi)存管理問題了饮焦。使用ARC來編程,可省去類中的許多樣板代碼窍侧。

ARC管理對象生命期的辦法基本上就是:在合適的地方插入保留及釋放操作县踢。在ARC環(huán)境下,變量的內(nèi)存管理語義總是通過方法名來體現(xiàn)伟件。ARC將此確定為開發(fā)者必須遵守的規(guī)則硼啤。

ARC只負(fù)責(zé)管理Objective-C對象的內(nèi)存。尤其要注意:CoreFoundation對象不歸ARC管理斧账,開發(fā)者必須適時調(diào)用CFRetain/CFRelease谴返。

在dealloc方法中只釋放引用并解除監(jiān)聽

在dealloc方法里,應(yīng)該做的事情就是釋放指向其它對象的引用咧织,并取消原來訂閱的鍵值觀測或NSNotificationCenter等通知亏镰,不要做其他事情。

如果對象持有文件描述符等系統(tǒng)資源拯爽,那么應(yīng)該專門編寫一個方法來釋放此種資源索抓。這樣的類要和其使用者約定“用完資源后必須調(diào)用close方法。

執(zhí)行異步任務(wù)的方法不應(yīng)在dealloc里調(diào)用;只能在正常狀態(tài)下執(zhí)行的那些方法也不應(yīng)在dealloc里調(diào)用逼肯,因?yàn)榇藭r對象已處于正在回收的狀態(tài)了耸黑。

編寫異常安全代碼時留意內(nèi)存管理問題

捕獲異常時,一定要注意將try塊內(nèi)所創(chuàng)立的對象清理干凈篮幢。

在默認(rèn)情況下大刊,ARC不生成安全處理異常所需的清理代碼。開啟編譯器標(biāo)志后三椿,可生成這種代碼缺菌,不過會導(dǎo)致應(yīng)用程序變大,而且會降低運(yùn)行效率搜锰。

以弱引用避免重復(fù)引用

將某些引用設(shè)為weak伴郁,可避免出現(xiàn)重復(fù)引用。

weak引用可以自動清空蛋叼,也可以不自動清空焊傅。自動清空是隨著ARC而引入的新特性,由runtime來實(shí)現(xiàn)狈涮,在具備自動清空功能的弱引用上狐胎,可以隨意讀取其數(shù)據(jù),因?yàn)檫@種引用不會指向已經(jīng)回收過的對象歌馍。

以自動釋放池塊降低內(nèi)存峰值

自動釋放池排布在棧中握巢,對象收到autorelease消息后,系統(tǒng)將其放入最頂端的池里松却。

合理運(yùn)用自動釋放池镜粤,可降低應(yīng)用程序的內(nèi)存峰值。

@autoreleasepool這種新式寫法能創(chuàng)建出更為輕便的自動釋放池玻褪。

用“僵尸對象”調(diào)試內(nèi)存管理問題

系統(tǒng)在回收對象時,可以不將其真的回收公荧,而是把它轉(zhuǎn)化為僵尸對象带射。通過環(huán)境變量NSZombieEnabled可開啟此功能。

系統(tǒng)會修改對象的isa指針循狰,令其指向特殊的僵尸類窟社,從而使該對象變?yōu)榻┦瑢ο蟆=┦惸軌蝽憫?yīng)所有的selector響應(yīng)方式為:打印一條包含消息內(nèi)容及其接受者的消息绪钥,然后終止應(yīng)用程序灿里。

不要使用retainCount

對象的保留計(jì)數(shù)看似有用,實(shí)則不然程腹,因?yàn)槿魏谓o定時間點(diǎn)上的絕對保留計(jì)數(shù)都無法反映對象生命期的全貌匣吊。

引入ARC后,retainCount方法就正式廢止了,在ARC下調(diào)用該方法會導(dǎo)致編譯器報錯色鸳。

六社痛、block與GCD

理解block的概念

block是C、C++命雀、Objective-C中的詞法閉包蒜哀。

block可接收參數(shù),也可返回值吏砂。

block可以分配在椖於或堆上,也可以是全局的狐血。分配在棧上的block可拷貝到堆里淀歇,這樣的話,就和標(biāo)準(zhǔn)的Objective-C對象一樣氛雪,具備引用計(jì)數(shù)了房匆。

為常用的block類型創(chuàng)建typedef

以typedef重新定義block類型,可以令block變量用起來更加簡單报亩。

定義新類型時應(yīng)遵循現(xiàn)有的命名習(xí)慣浴鸿,勿使其名稱與別的的類型相沖突。

不妨為同一個block簽名定義多個類型別名弦追。如果要重構(gòu)的代碼使用了block類型的某個別名岳链,那么只需修改相應(yīng)的typedef中的block簽名即可,無需改動其他typedef劲件。

用handler塊降低代碼分散程度

在創(chuàng)建對象時掸哑,使用內(nèi)聯(lián)的handler塊將相關(guān)業(yè)務(wù)邏輯一并聲明。

在有多個實(shí)例需要監(jiān)控時零远,如果采用委托模式苗分,那么經(jīng)常需要根據(jù)傳入的對象來切換,而若改用handler塊來實(shí)現(xiàn)牵辣,則可直接將block與相關(guān)對象放在一起摔癣。

設(shè)計(jì)API時如果用到了handler塊,那么可以增加一個參數(shù)纬向,使調(diào)用者可通過此參數(shù)來決定應(yīng)該把block安排在哪個隊(duì)列上執(zhí)行择浊。

用block引用其所屬對象時不要出現(xiàn)循環(huán)引用

如果block所捕獲的對象直接或間接的保留了block本身,那么就得當(dāng)心循環(huán)引用的問題逾条。

一定要找個適當(dāng)?shù)臅r機(jī)解除循環(huán)引用琢岩,而不能把責(zé)任推給API的調(diào)用者。

多用派發(fā)隊(duì)列师脂,少用同步鎖

派發(fā)隊(duì)列可用來表述同步語義担孔,這種做法要比使用@synchronized塊或NSLock對象更簡單江锨。

將同步與異步派發(fā)結(jié)合起來,可以實(shí)現(xiàn)與普通加鎖機(jī)制一樣的同步行為攒磨,而這么做卻不會阻塞執(zhí)行異步派發(fā)的線程泳桦。

使用同步隊(duì)列及柵欄塊,可以領(lǐng)同步行為更加高效娩缰。

多用GCD灸撰,少用performSelector系列方法

performSelector系列方法在內(nèi)存管理方面容易有疏失。它無法確定將要執(zhí)行的selector具體是什么拼坎,因而ARC編譯器就無法插入適當(dāng)?shù)膬?nèi)存管理方法浮毯。

performSelector系列方法所能處理的selector太過局限了,selector的返回值類型及發(fā)送給方法的參數(shù)個數(shù)都受到限制泰鸡。

如果想把人物放在另一個線程上執(zhí)行债蓝,那么最好不要用performSelector系列方法而是應(yīng)該把任務(wù)封裝到block里然后調(diào)用GCD機(jī)制的相關(guān)方法來實(shí)現(xiàn)。

掌握GCD及操作隊(duì)列的使用時機(jī)

在解決多線程與任務(wù)管理問題時盛龄,派發(fā)隊(duì)列并非唯一方案饰迹。

操作隊(duì)列提供了一套高層的Objective-C API,能實(shí)現(xiàn)純GCD所具備的絕大部分功能余舶,而且還能完成一些更為復(fù)雜的操作啊鸭,那些操作若改用GCD來實(shí)現(xiàn),則需另外編寫代碼匿值。

通過Dispatch Group機(jī)制根據(jù)系統(tǒng)資源狀況來執(zhí)行任務(wù)

一系列任務(wù)可貴如一個dispatch group之中赠制。開發(fā)者可以在這組任務(wù)執(zhí)行完畢時獲得通知。

通過dispatch group挟憔,可以在并發(fā)式派發(fā)隊(duì)列里同時執(zhí)行多項(xiàng)任務(wù)钟些。此時GCD會根據(jù)系統(tǒng)資源狀況來調(diào)度這些并發(fā)執(zhí)行的任務(wù)。開發(fā)者若自己來實(shí)現(xiàn)此功能绊谭,則需編寫大量代碼政恍。

使用dispatch_once來執(zhí)行只需運(yùn)行一次的線程安全代碼

經(jīng)常需要編寫只需執(zhí)行一次的線程安全代碼。通過GCD所提供的dispatch_once函數(shù)达传,很容易就能實(shí)現(xiàn)此功能篙耗。

標(biāo)記應(yīng)該聲明在static或global作用域中,這樣的話趟大,在把只需執(zhí)行一次的block傳給dispatch_once函數(shù)時,傳進(jìn)去的標(biāo)記也是相同的铣焊。

不要使用dispatch_get_current_queue

dispatch_get_current_queue函數(shù)的行為常常與開發(fā)者所預(yù)期的不同逊朽。此函數(shù)已廢棄,只應(yīng)做調(diào)試之用曲伊。

由于派發(fā)隊(duì)列是按層級來組織的叽讳,所以無法單用某個隊(duì)列對象來描述當(dāng)前隊(duì)列這一概念追他。

dispatch_get_current_queue函數(shù)用于解決由不可重入的代碼所引發(fā)的死鎖,然而能用此函數(shù)解決的問題岛蚤,通常也能改用“隊(duì)列特定數(shù)據(jù)”來解決邑狸。

七、系統(tǒng)框架

熟悉系統(tǒng)框架

許多系統(tǒng)框架都可以直接使用涤妒。其中最重要的是Foundation與CoreFoundation单雾,這兩個框架提供了構(gòu)建應(yīng)用程序所需的許多核心功能。

很多常見任務(wù)都能用框架來做她紫,例如音頻與視頻處理硅堆、網(wǎng)絡(luò)通信、數(shù)據(jù)管理等贿讹。

請記住渐逃,用純C寫成的框架與用Objective-C寫成的一樣重要,若想成為優(yōu)秀的Objective-C開發(fā)者民褂,應(yīng)該掌握C語言的核心概念茄菊。

多用塊枚舉,少用for循環(huán)

遍歷collection有4種方式赊堪。最基本的辦法是for循環(huán)面殖,其次是NSEnumerator遍歷方法及快速遍歷方法,最新雹食、最先進(jìn)的方式則是塊枚舉法畜普。

塊枚舉法本身就能通過GCD來并發(fā)執(zhí)行遍歷操作,無需另行編寫代碼群叶。而采用其他遍歷方式則無法輕易實(shí)現(xiàn)這一點(diǎn)吃挑。

若提前知道待遍歷的collection含有何種對象,則應(yīng)修改塊簽名街立,指出對象的具體類型舶衬。

隊(duì)自定義其內(nèi)存管理語義的collection使用無縫橋接

通過無縫橋接技術(shù),可以在Foundation框架中的Objective-C對象與CoreFoundation框架中的C語言數(shù)據(jù)結(jié)構(gòu)之前來回轉(zhuǎn)換赎离。

在CoreFoundation層面創(chuàng)建collection時逛犹,可以指定許多回調(diào)函數(shù),這些函數(shù)表示此collection應(yīng)如何處理其元素梁剔。然后虽画,可運(yùn)用無縫橋接技術(shù),將其轉(zhuǎn)換成具備特殊內(nèi)存管理語義的Objective-C collection荣病。

構(gòu)建緩存是選用NSCachae而非NSDictionary

實(shí)現(xiàn)緩存時應(yīng)選用NSCache而非NSDictionary對象码撰。因?yàn)镹SCache可以提供優(yōu)雅的自動刪減功能,而且是線程安全的个盆,此外脖岛,它與字典不同朵栖,并不會拷貝鍵。

可以給NSCache對象設(shè)置上限柴梆,用以限制緩存中的對象總個數(shù)及總成本陨溅,而這些尺度則定義了緩存刪減其中對象的時機(jī)。但是絕對不要把這些尺度當(dāng)成可靠的硬限制绍在,他們僅對NSCache起指導(dǎo)作用门扇。

將NSPurgeableData與NSCache搭配使用,可實(shí)現(xiàn)自動清除數(shù)據(jù)的功能揣苏,也就是說悯嗓,當(dāng)NSPurgeableData對象所占內(nèi)存為系統(tǒng)丟棄時,該對象自身也會從緩存中移除卸察。

如果緩存使用得當(dāng)脯厨。那么應(yīng)用程序的響應(yīng)速度就能提高。只有那種重新計(jì)算起來很費(fèi)事的數(shù)據(jù)坑质,才值得放入緩存合武,比如那些需要從網(wǎng)絡(luò)獲取或從磁盤讀取的數(shù)據(jù)。

精簡initialize與load的實(shí)現(xiàn)代碼

在加載階段涡扼,如果實(shí)現(xiàn)了load方法稼跳,那么系統(tǒng)就會調(diào)用它。分類里也可以定義此方法吃沪,類load方法要比分類中的先調(diào)用汤善。與其他方法不同,load方法不參與覆寫機(jī)制票彪。

首次使用某個類之前红淡,系統(tǒng)會向其發(fā)送initialize消息。由于此方法遵從普通的復(fù)寫規(guī)則降铸,所以通常應(yīng)該在里面判斷當(dāng)前要初始化的是哪個類在旱。

load與initialize方法都應(yīng)該實(shí)現(xiàn)的精簡一些,這有助于保持應(yīng)用程序的響應(yīng)能力推掸,也能減少引入依賴環(huán)的幾率桶蝎。

無法在編譯期設(shè)定的全局常量,可以放在initialize方法里初始化谅畅。

別忘了NSTimer會保留其目標(biāo)對象

NSTimer對象會保留其目標(biāo)登渣,直到計(jì)時器本身失效為止,調(diào)用invalidate方法可令計(jì)時器失效毡泻,另外胜茧,一次性的計(jì)時器在觸發(fā)完任務(wù)之后也會失效。

反復(fù)執(zhí)行任務(wù)的計(jì)時器牙捉,很容易引入循環(huán)引用竹揍,進(jìn)入過這種計(jì)時器的目標(biāo)對象又保留了計(jì)時器本身,那肯定會導(dǎo)致循環(huán)引用邪铲。這種循環(huán)引用芬位,可能是直接發(fā)生的,也可能是通過對象圖里的其他對象間接發(fā)生的带到。

可以擴(kuò)充NSTimer的功能昧碉,用塊來打破循環(huán)引用。不過揽惹,除非NSTimer將來在公共接口里提供此功能被饿,否則必須創(chuàng)建分類,將相關(guān)實(shí)現(xiàn)代碼加入其中搪搏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末狭握,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子疯溺,更是在濱河造成了極大的恐慌论颅,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件囱嫩,死亡現(xiàn)場離奇詭異恃疯,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)墨闲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門今妄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鸳碧,你說我怎么就攤上這事盾鳞。” “怎么了杆兵?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵雁仲,是天一觀的道長。 經(jīng)常有香客問我琐脏,道長攒砖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任日裙,我火速辦了婚禮吹艇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昂拂。我一直安慰自己受神,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布格侯。 她就那樣靜靜地躺著鼻听,像睡著了一般财著。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撑碴,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天撑教,我揣著相機(jī)與錄音,去河邊找鬼醉拓。 笑死伟姐,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亿卤。 我是一名探鬼主播愤兵,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼排吴!你這毒婦竟也來了秆乳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钻哩,失蹤者是張志新(化名)和其女友劉穎矫夷,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體憋槐,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡双藕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了阳仔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忧陪。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖近范,靈堂內(nèi)的尸體忽然破棺而出嘶摊,到底是詐尸還是另有隱情,我是刑警寧澤评矩,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布叶堆,位于F島的核電站,受9級特大地震影響斥杜,放射性物質(zhì)發(fā)生泄漏虱颗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一蔗喂、第九天 我趴在偏房一處隱蔽的房頂上張望忘渔。 院中可真熱鬧,春花似錦缰儿、人聲如沸畦粮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宣赔。三九已至预麸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間儒将,已是汗流浹背师崎。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留椅棺,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓齐蔽,卻偏偏與公主長得像两疚,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子含滴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容