iOS技巧、特性及規範,ios技巧規範
一、編譯器特性
1、ARC。
ARC是編譯器特性。項目中使用了ARC,編譯器會在項目編譯的時候自動添加OC對象計數器release代碼。並且使用了ARC,項目中將不允許出現release、retain、retainCount和[super dealloc]代碼。
ARC不同於Java和.Net中的記憶體回收,Java和.Net中的記憶體回收是運行時特性。ARC只是將OC對象的計數器自動減1。非OC對象,像常見的資料類型、enum枚舉和struct結構體不參與ARC,系統會自動銷毀回收。(註:OC對象計數器在一個對象中佔4個位元組,當計數器為0時,如果該OC對象被strong強指標引用,那麼此OC對象將成為殭屍對象不可再次訪問,當然也無法“複活”該對象,應當手動將strong強指標置為nil;如果該OC對象被weak弱指標引用,那麼此OC對象變為殭屍對象的時候,weak弱指標將自動銷毀。)
2、@class
@class是在類的標頭檔中出現的。使用@class主要解決兩個問題:
①在非ARC的項目中,解決因類之間的相互引用,導致OC對象計數器無法減為0的問題。在其中一個類標頭檔中引用另一個類的標頭檔使用@class,並且將其中一個類的所有OC對象指標設為assign類型即可。
②提高編譯器特性。使用@class就相當於一個聲明,告訴另一個類包含哪些成員變數和方法,具體在.m使用的時候,只需再#import此類的.h檔案即可。如果不是用@class聲明類的引用,全都是在.h檔案中直接#import另一個類的.h檔案,那麼當一個.h檔案改變,編譯器在編譯的時候就會再複製一遍此.h標頭檔,加入有上萬個這樣的應用,編譯器就得複製一萬遍。使用@class就可以不用複製,這樣就提高了編譯器效能。
3、[]
對於NSArray和NSDictionary,當需要直接根據索引index或者關鍵字key取得相應的值的時候,就可以像直接通過[index]或者[key]獲得。注意,通過此方法擷取到的對象都是id類型,想要再訪問指定物件類型的方法或者成員變數還需要自己轉一下。(註:為什麼通過[]擷取到的對象是id類型?因為[index]相當於調用了NSArray對象的objectAtIndex方法,[key]相當於調用了objectForKey,這兩個方法返回的都是id類型的對象。)
4、@()和@20
@()和@20是在int整型轉換為OC對象NSNumber的時候用到的。比如,@20就是將整型20轉換為NSNumber的OC物件類型,進而可以在NSArray或者NSDictionary中使用。(註:NSArray和NSDictionary只允許添加OC對象作為元素。)。@(),是將常見資料類型臨時變數轉換為指定OC類型。比如int a = 20;NSNumber *aa = @(a);這樣就將臨時變數a的整型值轉換為了NSNumber的OC類型。不可以這樣寫@a,一寫就報錯。
二、效能
1、SEL
SEL即Selector。SEL是指向類中方法的指標類型。通常情況下,當對象或者類調用對象方法或者類方法的時候,都先要將調用的方法封裝成SEL類型,然後根據SEL類型資料找到對應類中所調用方法的地址,最後就是調用。這樣一個對象或者類調用指定方法就經過了2步,如果涉及到同一個方法多次頻繁的調用還是每次都要經過SEL這兩步的話,無疑會耗費一定的效能。此時就可以將SEL單獨儲存起來,每次調用就可以直接根據SEL類型的指標地址找到對應方法進行執行。
2、nonatomic
在一個類的標頭檔中聲明一個成員變數時,系統預設將此變數聲明為atomic,atonmic就是原子的意思,是在多線程中使用,防止同一個成員或對象同時被多個線程同時訪問造成死結。預設是atomic,項目在編譯的時候系統會自動在後台添加很多代碼,平時不牽涉到多線程,此處就可以手動設定為nonatomic,提高效能。
3、[UIImage imageNamed:]
一個UIImageView使用此方法訪問顯示一個圖片,系統會自動將此圖片在記憶體中產生一份緩衝,如果不從記憶體中清除此緩衝,它將一直佔用記憶體。如果使用imageWithContentsOfFile,當UIImageView由一張圖片顯示為另一張圖片的時候,系統就會自動將上一張圖片從記憶體中銷毀移除。
4、自訂UITableViewCell,如果一張圖片只是控制了其hidden屬性,那麼就可以在UITableViewCell初始化的時候將UIImageView的image設定為此圖片,避免在UITableViewCell從緩衝池中迴圈利用重複設定資料設定圖片的時候造成的記憶體消耗。
5、自訂UITableViewCell出現高度不一致的時候,需要引入frame模型,在擷取到資料以後馬上計算每一個UITableViewCell的frame,使用的時候直接設定計算好的高度就可以了。避免了在UITableView上下滾動的時候造成的重複計算消耗效能造成的卡頓現象。
三、技巧
1、介面上顯示一道線,在WPF中可以使用Border或者Line現成的控制項來做,在OC裡面蘋果官方使用的是UIView。如果是橫線,則UIView的height為1,同理豎線的情況with為1。
2、UITextField左右兩側有leftView和rightView。如果我們想在使用者輸入的時候自動在左側留有空隙,那麼就可以使用指定leftView為[[UIView alloc] initWithRect:CGRectMake(0, 0, 8, 0)];
3、給一個UIButton設定一個表徵圖,且此表徵圖不能伸縮變形顯示,此時可以設定此UIButton的image來展示,而不是BackgroundImage。
4、映像平鋪技術。比如QQ聊天視窗,每個人發的訊息。其實程式就是指定了在一張圖片的上、下、左、右多少範圍內當圖片展開的時候不變形,範圍內的地區自動平鋪填充圖形。此技術在Win8裡面叫NineGrid(九切片)。
四、調試
1、錯誤提示關鍵字:forUndefinedKey。一看就知道StoryBoard裡面的線連錯了。
2、Unrecoganized seletor sent to instance。一看就是到對象或類的方法為找到。
此種情況比較常見的原因有兩點:
①、子類調用父類的自訂建構函式初始化,父類方法沒有使用self,結果返回的還是父類對象,調用了子類的方法。
②、在定義對象方法的時候,傳回值使用了id類型而不是instancetype。如上面所說,id類型是不能自動轉換為指定對象,預設返回的是任意類型的對象,比如一個要返回一個Person對象,沒有定義length成員,此時用NSString類型的指標是可以去指向該對象的,那訪問NSString的length成員就會出現此錯誤。解決方案,可以通過強轉為Person對象,或者將傳回型別id換位instancetype。那是不是所有使用id的地方都可以換位instancetype呢?不是。只有在id作為傳回型別的時候才可以替換為instancetype。
3、has been modified。一看就知道清下項目緩衝就可以解決。
五、布局
當我們修改了介面啟動並執行時候看不到變化,此時就可以試著去去掉autolayout。
六、.pch檔案
1、盡量將我們自己定義的東西放在@ifdef __OBJC__ 裡面。
舉個例子:比如在.pch檔案裡匯入了一個.h標頭檔,#import "Person.h"。並且沒有寫在@ifdef __OBJC__裡面,此時我們在項目中寫一個.c的檔案,一運行就會報很多錯誤。為什麼呢?因為在.pch匯入#import的.h檔案,會在項目所有檔案中預設匯入#import該.h標頭檔,但C語言的.c程式需要#include才可以匯入.h標頭檔,使用#import顯然不行,所以報錯。
2、一定要使用自訂的日誌列印策略,不然在項目發布的時候還會包含很多日誌列印的代碼,無疑會影響效能。自訂日誌列印策略如下:
所以,看一個項目代碼,首先去看.pch檔案。
七、規範
類名和函數名單詞首字母都大寫,方法名和變數名單詞第一個首字母小寫,其他單字首大寫。
八、理解
1、為什麼UITableViewCell需要Identifier,而UIDatePick的自訂View不需要。
UITableViewCell使用Identifier主要考慮到以下兩點:
①不同資料用不同cell模板,就可以根據Identifier不同從緩衝池中迴圈利用指定的cell模板。
②、根據Identifier從緩衝池中去除已存在的模板,迴圈利用,提高效能。
UIDatePick的View都是一樣的模板,不存在同一資料來源不同模板的情況,所以不需要Identifier直接去使用resuming就行了。
此外還要注意awakeFromNib、layoutSubView以及didMoveToSuperView方法的用法。
iOS還在學習中,有理解不到位或者錯誤的地方,還請各路大神指點。