天天看點

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

    品質問題不僅僅是商品應該注重的,在移動互聯占據人們各個生活領域的前提下,産品品質更顯重要,以最具人氣和潛力的iOS為例,iOS從系統研發和用戶端軟體開發環節對品質的要求異常高,在注重使用者體驗的同時提升産品品質,這也是很多使用者非iOS不用的原因,iOS系統已經讓移動網際網路的品質得到更新。那麼我們在開發iOS産品時,如何提高它的品質呢?     涉及到品質問題,這就是一個很大的話題,包括很多方面,比如代碼書寫的品質,開發流程的規範,項目管理的到位,測試的最後把關等各個環節。編碼需要規範,命名需要有意義;接口低耦合、高内聚、易擴充,代碼能重用、避免重複代碼;送出代碼後需要做CodeReview;Release前,自測需要充分,包括單元測試、和其他子產品(伺服器)的聯調測試,網絡性能測試,不同機型、不同系統版本、越獄與否等各個方面的測試;通過冒煙測試後才交于QA測試等等。在這裡,我們主要分享從開發人員的角度如何提高産品品質,包含的内容如下:  

避免異常:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

從上面可以看到,iOS開發中常見的異常包括以下幾種:

NSInvalidArgumentException

NSRangeException

NSGenericException

NSInternalInconsistencyException

NSFileHandleOperationException  

NSInvalidArgumentException

非法參數異常(NSInvalidArgumentException)是 Objective - C 代碼最常出現的錯誤,是以平時在寫代碼的時候,需要多加注意,加強對參數的檢查,避免傳入非法參數導緻異常,其中尤以nil參數為甚。

集合資料的參數傳遞

比如NSMutableArray, NSMutableDictionary的資料操作

(1) 不能删除nil的key

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

(2) NSDictionary不能添加nil的對象

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

(3) 不能插入nil的對象

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

(4) 其他一些nil參數

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

其他一些API的使用

(1) NSDictionary不能删除nil的key

APP一般都會有網絡操作,免不了使用網絡相關接口,比如NSURL的初始化,不能傳入nil的http位址:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

未實作的方法

(1) .h檔案裡修改了函數名,卻忘了修改.m檔案裡對應的函數名;或者頭檔案裡定義了函數,.m檔案裡沒有實作

(2) 使用第三方庫時,沒有添加”-ObjC” flag

(3) MRC時,大部分情況下是因為對象被提前release了,在你心裡不希望他release的情況下,指針還在,對象已經不在了。           比如:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析
提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

(4) 對象類型使用不當    

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析
提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

因為imagenS本來是NSDictionary的對象,被當做NSString來處理了

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

類似的,NSDictionary的對象被當做NSArrary來處理了

NSRangeException

越界異常(NSRangeException)也是比較常出現的異常,有如下幾種類型:

數組最大下标處理錯誤

比如數組長度count, index的下标範圍[0, count -1], 在開發時,可能index的最大值超過數組的範圍;

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

下标的值是其他變量指派

這樣會有很大的不确定性, 可能是一個很大的整數值

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析
提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

這裡的值達到32位和64位整數的最大值,肯定是一個不正常的參數,比如:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

如果找不到str ,則傳回NSNotFound,32位下它就是2147483647,64位下18446744073709551615 ,将它作為參數傳遞則會導緻NSRangeException。

使用空數組

如果一個數組剛剛初始化,還是空的,就對它進行相關操作

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

是以,為了避免NSRangeException的發生,必須對傳入的index參數進行合法性檢查,是否在集合資料的個數範圍内。

NSGenericException

NSGenericException這個異常最容易出現在foreach操作中,在for in循環中如果修改所周遊的數組,無論你是add或remove,都會出錯,比如:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

  執行上面的代碼會出現以下的錯誤:  

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

原因就在這 "for in",它的内部周遊使用了類似 Iterator進行疊代周遊,一旦元素變動,之前的元素全部被失效,是以在foreach的循環當中,最好不要去進行元素的修改動作,若需要修改,循環改為for周遊,由于内部機制不同,不會産生修改後結果失效的問題。

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

NSMallocException

這也是記憶體不足的問題,無法配置設定足夠的記憶體空間

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

NSFileHandleOperationException

處理檔案時的一些異常,最常見的還是存儲空間不足的問題,比如應用頻繁的儲存文檔,緩存資料或者處理比較大的資料:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

      是以在檔案處理裡,需要考慮到手機存儲空間的問題。  

二、錯誤處理

在進行函數調用的時候,如果有NSError的參數傳遞,最好都處理以下,特别是一些網絡和檔案的處理,比如:

檔案操作錯誤 比如在删除檔案時,有可能發生錯誤,我們需要做一些處理

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

網絡處理錯誤 在使用NSURLConnection進行網絡請求時,發生錯誤是難免的,必須做相應處理

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

三、本地緩存的相容處理

在APP的運作過程中,難免會有I/O的操作,一般的情況,從技術的角度來看也不會出什麼問題,但是業務邏輯上可能就需要特别注意了,比如APP更新版本後,可能儲存緩存資料的格式發生變化了,讀取資料後的處理邏輯也就相應發生變化,這時就需要考慮相容舊版本資料的處理,否則對更新使用者了說,很可能由于異常發生崩潰。         

四、解析網絡資料

用戶端開發時,對接收到的伺服器資料,需要特别小心,因為經過網絡傳輸回來的資料都是不可信的,什麼問題都可能發生,比如協定中該有的字段沒有,是整數型的字段結果傳了一個子串,Json格式的内容變成xml了…,是以我們在解析伺服器資料時,需要有充分的異常處理機制。

五、代碼靜态檢查

在開發完成後,需要對代碼進行靜态檢查,這樣能發現一些記憶體洩露以及一些warning。

記憶體洩露

MRC

在MRC的時候,記憶體洩露是個大問題,一不小心就會中招

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

注意上面的代碼并不是L63行存在洩漏,我們點選“Potential leak of an object”前面的箭頭,訓示會出現一些變化,如下圖。

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

alloc一個對象的時候,其記憶體計數記憶體計數(retain count)+1

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析
提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

因為content的setter方發會将object的記憶體計數+1,如下代碼,content是retain屬性。執行完L62代碼後,self.content的記憶體計數就為 2

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

建議修改方案:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

ARC

在ARC下,這方面的問題就少很多了,但也還是會出現的,比如:

(1)使用CF CG有關的函數,記憶體的釋放還是需要手動調用的,不調用則會造成記憶體洩漏

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

CFUUIDRef和CFStringRef都需要手動釋放

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

CGImageRef類似也需要手動釋放

  (2) Runtime方法中的

class_copyIvarList

class_copyMethodList

這些方法傳回的對象,也需要手動釋放(free)

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

(3) 如果iOS中使用C/C++程式設計      比如使用Openssl的RSA接口,用到一些記憶體的配置設定操作,使用結束需要釋放

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

在iOS中,怎麼避免記憶體洩漏的産生呢?除了開發經驗的積累,我們也可以通過兩個方法來發現記憶體洩漏,以便及時修複,一個就是上面講到的靜态分析(Analyze),比較簡單;對于靜态沒有檢測出來的記憶體洩露問題,需要使用動态的方法,下一節來分享。  

無效資料監測(Dead store)

Unused、Never read....這個比較簡單,修改即可。  

邏輯錯誤監測(Logic error)

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

Tag不等于1、2和3的時候,就會出現很問題了。len is a garbage value。建議在聲明變量時,同時進行初始化。  

其他一些warning

對完美主義者來說,warning在Xcode裡始終都比較礙眼,直接消除。  

Instruments分析

Analyze分析記憶體洩露不能把所有的記憶體洩露查出來,有的記憶體洩露是在運作時,使用者操作時才産生的。在 C、C++混編時,對于C++的記憶體配置設定,也是需要手動釋放,比如iOS中使用Openssl來進行RSA的加解密操作,其中就有很多的記憶體操作,如果不進行手動釋放,Analyze是檢查不出來的,這個時候就需要用到Instruments了。

初始化

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

釋放的代碼注釋掉

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

這個時候使用Analyze分析,一點記憶體洩漏也沒有,我們使用Instruments來分析

“Product” -> “Profile”:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

按上面操作,build成功後跳出Instruments工具,選擇Leaks工具,這時候Instruments工具就運作起來了,顯示效果如下:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

點選上面的”紅色的圓圈”,才會啟動對應的APP,這時”紅色的圓圈”變成”黑色的正方形”:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

這時使用者就可以在APP上任意操作,檢視記憶體使用情況,選擇”Leak Checks”項,右邊的圖中,如果是”綠色的勾”表示記憶體使用正常,”紅色的叉”則表示有記憶體洩漏,這時點選”黑色的正方形”,讓APP暫停下來。

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

這時你隻要在”Reponsible Frame”中輕按兩下對應的方法,就會跳轉到具體的代碼,比如輕按兩下”MS_RSA_Public_E”: 

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析

代表malloc後沒有使用free釋放OutBuf的記憶體。

修改如下:

提高iOS開發品質的一些事 避免異常: 二、錯誤處理 三、本地緩存的相容處理 四、解析網絡資料 五、代碼靜态檢查 Instruments分析