涉及到質量問題,這就是一個很大的話題,包括不少方面,好比代碼書寫的質量,開發流程的規範,項目管理的到位,測試的最後把關等各個環節。編碼須要規範,命名須要有意義;接口低耦合、高內聚、易擴展,代碼能重用、避免重複代碼;提交代碼後須要作CodeReview;Release前,自測須要充分,包括單元測試、和其餘模塊(服務器)的聯調測試,網絡性能測試,不一樣機型、不一樣系統版本、越獄與否等各個方面的測試;經過冒煙測試後才交於QA測試等等。在這裏,咱們主要分享從開發人員的角度如何提升產品質量,包含的內容以下:數組
從上面能夠看到,iOS開發中常見的異常包括如下幾種:
NSInvalidArgumentException
NSRangeException
NSGenericException
NSInternalInconsistencyException
NSFileHandleOperationException緩存
非法參數異常(NSInvalidArgumentException)是 Objective - C 代碼最常出現的錯誤,因此平時在寫代碼的時候,須要多加註意,增強對參數的檢查,避免傳入非法參數致使異常,其中尤以nil參數爲甚。服務器
(1) NSDictionary不能刪除nil的key
(2) NSDictionary不能添加nil的對象
(3) 不能插入nil的對象
(4) 其餘一些nil參數
網絡
越界異常(NSRangeException)也是比較常出現的異常,有以下幾種類型:函數
好比數組長度count, index的下標範圍[0, count -1], 在開發時,可能index的最大值超過數組的範圍;
工具
這樣會有很大的不肯定性, 多是一個很大的整數值性能
這裏的值達到32位和64位整數的最大值,確定是一個不正常的參數,好比:單元測試
若是找不到str ,則返回NSNotFound,32位下它就是2147483647,64位下18446744073709551615 ,將它做爲參數傳遞則會致使NSRangeException。測試
若是一個數組剛剛初始化,仍是空的,就對它進行相關操做ui
因此,爲了不NSRangeException的發生,必須對傳入的index參數進行合法性檢查,是否在集合數據的個數範圍內。
NSGenericException這個異常最容易出如今foreach操做中,在for in循環中若是修改所遍歷的數組,不管你是add或remove,都會出錯,好比:
執行上面的代碼會出現如下的錯誤:
緣由就在這 "for in",它的內部遍歷使用了相似 Iterator進行迭代遍歷,一旦元素變更,以前的元素所有被失效,因此在foreach的循環當中,最好不要去進行元素的修改動做,若須要修改,循環改成for遍歷,因爲內部機制不一樣,不會產生修改後結果失效的問題。
這也是內存不足的問題,沒法分配足夠的內存空間
處理文件時的一些異常,最多見的仍是存儲空間不足的問題,好比應用頻繁的保存文檔,緩存資料或者處理比較大的數據:
因此在文件處理裏,須要考慮到手機存儲空間的問題。
在進行函數調用的時候,若是有NSError的參數傳遞,最好都處理如下,特別是一些網絡和文件的處理,好比:
文件操做錯誤
好比在刪除文件時,有可能發生錯誤,咱們須要作一些處理
網絡處理錯誤
在使用NSURLConnection進行網絡請求時,發生錯誤是不免的,必須作相應處理
在APP的運行過程當中,不免會有I/O的操做,通常的狀況,從技術的角度來看也不會出什麼問題,可是業務邏輯上可能就須要特別注意了,好比APP升級版本後,可能保存緩存數據的格式發生變化了,讀取數據後的處理邏輯也就相應發生變化,這時就須要考慮兼容舊版本數據的處理,不然對升級用戶了說,極可能因爲異常發生崩潰。
客戶端開發時,對接收到的服務器數據,須要特別當心,由於通過網絡傳輸回來的數據都是不可信的,什麼問題均可能發生,好比協議中該有的字段沒有,是整數型的字段結果傳了一個子串,Json格式的內容變成xml了…,因此咱們在解析服務器數據時,須要有充分的異常處理機制。
在開發完成後,須要對代碼進行靜態檢查,這樣能發現一些內存泄露以及一些warning。
在MRC的時候,內存泄露是個大問題,一不當心就會中招
注意上面的代碼並非L63行存在泄漏,咱們點擊「Potential leak of an object」前面的箭頭,指示會出現一些變化,以下圖。
alloc一個對象的時候,其內存計數內存計數(retain count)+1
由於content的setter方發會將object的內存計數+1,以下代碼,content是retain屬性。執行完L62代碼後,self.content的內存計數就爲 2
建議修改方案:
在ARC下,這方面的問題就少不少了,但也仍是會出現的,好比:
使用CF CG有關的函數,內存的釋放仍是須要手動調用的,不調用則會形成內存泄漏
CFUUIDRef和CFStringRef都須要手動釋放
CGImageRef相似也須要手動釋放
在iOS中,怎麼避免內存泄漏的產生呢?除了開發經驗的積累,咱們也能夠經過兩個方法來發現內存泄漏,以便及時修復,一個就是上面講到的靜態分析(Analyze),比較簡單;對於靜態沒有檢測出來的內存泄露問題,須要使用動態的方法,下一節來分享。
Unused、Never read....這個比較簡單,修改便可。
Tag不等於一、2和3的時候,就會出現很問題了。len is a garbage value。建議在聲明變量時,同時進行初始化。
對完美主義者來講,warning在Xcode裏始終都比較礙眼,直接消除。
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的內存。
修改以下: