標籤:

iOS開發質量的那些事

質量問題不僅僅是商品應該注重的,在移動互聯佔據人們各個生活領域的前提下,產品質量更顯重要,以最具人氣和潛力的iOS為例,iOS從系統研發和客戶端軟體開發環節對質量的要求異常高,在注重用戶體驗的同時提升產品質量,這也是很多用戶非iOS不用的原因,iOS系統已經讓移動互聯網的品質得到升級。那麼我們在開發iOS產品時,如何提高它的質量呢?

涉及到質量問題,這就是一個很大的話題,包括很多方面,比如代碼書寫的質量,開發流程的規範,項目管理的到位,測試的最後把關等各個環節。編碼需要規範,命名需要有意義;介面低耦合、高內聚、易擴展,代碼能重用、避免重複代碼;提交代碼後需要做CodeReview;Release前,自測需要充分,包括單元測試、和其他模塊(伺服器)的聯調測試,網路性能測試,不同機型、不同系統版本、越獄與否等各個方面的測試;通過冒煙測試後才交於QA測試等等。在這裡,我們主要分享從開發人員的角度如何提高產品質量,包含的內容如下:

一、避免異常:

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

  • NSInvalidArgumentException

  • NSRangeException

  • NSGenericException

  • NSInternalInconsistencyException

  • NSFileHandleOperationException

NSInvalidArgumentException

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

1. 集合數據的參數傳遞

比如NSMutableArray, NSMutableDictionary的數據操作

(1) NSDictionary不能刪除nil的key

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

(3) 不能插入nil的對象

(4) 其他一些nil參數

2. 其他一些API的使用

APP一般都會有網路操作,免不了使用網路相關介面,比如NSURL的初始化,不能傳入nil的http地址:

3. 未實現的方法

(1) .h文件里函數名,卻忘了修改.m文件里對應的函數名

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

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

比如:

NSRangeException

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

1. 數組最大下標處理錯誤

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

2. 下標的值是其他變數賦值

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

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

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

3. 使用空數組

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

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

NSGenericException

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

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

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

NSMallocException

這也是內存不足的問題,無法分配足夠的內存空間

NSFileHandleOperationException

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

所以在文件處理里,需要考慮到手機存儲空間的問題。

二、錯誤處理

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

文件操作錯誤

比如在刪除文件時,有可能發生錯誤,我們需要做一些處理

網路處理錯誤

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

三、本地緩存的兼容處理

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

四、解析網路數據

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

五、代碼靜態檢查

在開發完成後,需要對代碼進行靜態檢查,這樣能發現一些內存泄露以及一些warning。

1. 內存泄露

(1) MRC

在MRC的時候,內存泄露是個大問題,一不小心就會中招

注意上面的代碼並不是L63行存在泄漏,我們點擊「Potential leak of an object」前面的箭頭,指示會出現一些變化,如下圖。

alloc一個對象的時候,其內存計數內存計數(retain count)+1

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

建議修改方案:

(2) ARC

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

使用CF CG有關的函數,內存的釋放還是需要手動調用的,不調用則會造成內存泄漏

CFUUIDRef和CFStringRef都需要手動釋放

CGImageRef類似也需要手動釋放

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

2. 無效數據監測(Dead store)

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

3. 邏輯錯誤監測(Logic error)

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

4. 其他一些warning

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

六、Instruments分析

Analyze分析內存泄露不能把所有的內存泄露查出來,有的內存泄露是在運行時,用戶操作時才產生的。在 C、C++混編時,對於C++的內存分配,也是需要手動釋放,比如iOS中使用Openssl來進行RSA的加解密操作,其中就有很多的內存操作,如果不進行手動釋放,Analyze是檢查不出來的,這個時候就需要用到Instruments了。

初始化

釋放的代碼注釋掉

這個時候使用Analyze分析,一點內存泄漏也沒有,我們使用Instruments來分析

"Product」 -> 「Profile":

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

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

這時用戶就可以在APP上任意操作,查看內存使用情況,選擇」Leak Checks」項,右邊的圖中,如果是」綠色的勾」表示內存使用正常,」紅色的叉」則表示有內存泄漏,這時點擊」黑色的正方形」,讓APP暫停下來。

這時你只要在」Reponsible Frame」中雙擊對應的方法,就會跳轉到具體的代碼,比如雙擊」MS_RSA_Public_E」:

代表malloc後沒有使用free釋放OutBuf的內存。

修改如下:

weixin.qq.com/r/VjuLk3D (二維碼自動識別)


推薦閱讀:

iOS 的融合與 AR 的崛起
[貝聊科技]AsyncDisplayKit近一年的使用體會及疑難點
破一下 Apple 與 PRC 領土有關的兩條謠言
你對 OS X 10.11 / iOS 9 的預設中文介面顯示字體有哪些期待?
iOS 10.2.1正式發布 修複數十個安全漏洞

TAG:iOS | iOS开发 |