作為乙個剛畢業從事ios開發不久的人,最初同事以及導師都叮囑我寫**的時候一定要注意異常情況,底線就是不能寫出任何有可能造成崩潰的**。實際上,專案中有監測崩潰的工具,而且review的時候也會很嚴格檢查,所以基本上那種有可能造成崩潰的**基本都會在上線前修正。
但就在前些天,客戶端發生了大面積一開啟就閃退的問題,影響非常嚴重,後來查出是引入的其他部門的sdk沒有進行型別判斷而導致的崩潰。或許是開發人員的不小心,但我覺得更多的是平時沒有養成習慣,沒有考慮到對於乙個擁有千萬級別使用者的應用來說,即使是萬分之一的崩潰概率,也會有數千個使用者崩潰,這在競爭激烈的網際網路市場,是不能被容忍的。
我平時也沒有過度重視,因為我總覺得理論上應該不可能崩潰,但是實際的場景太多,理論上不可能並不是百分百不可能,作為足夠嚴謹的開發人員,必須守住自己的底線,不只是知道什麼情況會造成崩潰,而是要養成一種程式設計習慣,所以特意分析了各種崩潰的情況。
nsarray *firstnames = @[@"roy", @"mike", @"jordan"];
nsstring *name = firstnames[3]; // 崩潰
崩潰資訊:
分析:可以看出當前陣列的範圍是0..2,當前下標超出了範圍,即訪問了未知的記憶體空間
注:除了陣列可能越界之外,字串也有可能越界,例如執行substringwithrange:訊息時如果傳遞了過大的範圍也會崩潰
複製**
陣列nsstring *name;
nsarray *firstnames = @[@"roy", @"mike", @"jordan", name]; //崩潰
崩潰資訊:
*****
分析:通過崩潰資訊可以很清楚看到是因為在字典初始化的時候插入了nil,實際上字面量語法是一種語法糖,本質是先建立了乙個陣列,然後把方括號內的所有物件新增到這個陣列中
注:字面量語法讓**更加簡潔,也能及時發現錯誤,但是最後建立的陣列是不可變的
複製**
字典nsnumber *jordanage;
nsdictionary *ages = @; //崩潰
崩潰資訊:
*****
分析:同上面原因一樣,都是插入了nil而導致的崩潰
注:當key為nil的時候插入也會崩潰
複製**
id person = @"person";
[person objectforkey:@"name"]; //崩潰
崩潰資訊:
*****
分析:person物件無法執行objectforkey:訊息,所以最後崩潰了
注:在用objective-c語言編碼時,我們會常常使用id型別更加便利地宣告變數,但在執行訊息前一定要確定它是否能響應,可使用respondstoselector:檢查。最常見的場景是呼叫**方法,即使指定了**物件,也不一定保證**實現了相應方法(協議裡還有可選實現的方法)
複製**
float number = nan;
nsdictionary *dict = @;
nsdata *data = [nsjsonserialization datawithjsonobject:dict options:nsjsonwritingsortedkeys error:nil];
崩潰資訊:
*****
分析:可以先來判斷dict物件是否能被轉換成json資料:
bool isvalidjsonobject = [nsjsonserialization isvalidjsonobject:dict];
isvalidjsonobject的結果是no,也就是dict物件無法被轉換為json資料,即nan型別不能被用於json物件中
注:當進行不正常的數**算時不只是會產生nan型別,也有可能產生+inf型別,雖然並不會直接造成崩潰,但有可能在用它們進行其他操作的時候會有可能造成崩潰。通過isnan(x)和isinf(x)方法可以判斷nan和inf型別
複製**
nsstring *text;
nsattributedstring *attributedtext = [[nsattributedstring alloc] initwithstring:text]; // 崩潰
崩潰資訊:
*****
分析:從崩潰資訊中可以很明顯看到是因為傳入的變數值為nil而崩潰
注:構造nsmutablestring時,如果傳入的字串為nil也會崩潰
複製**
uitableviewcell *cell = [tableview
dequeuereusablecellwithidentifier:@"reuseidentifier"
forindexpath:indexpath] // 崩潰
複製**
有一種情況,就是伺服器端傳遞資料給客戶端,客戶端將其解析成模型物件,然後取模型裡的值插入字面量語法構造的陣列或者字典中。如果伺服器端發生了問題,而客戶端沒有保護措施就會受到連累,當然實際上伺服器端百分之九十九的概率是不可能發生問題的,所以很多人(包括我)也理所當然不會去特意多寫一些多餘的防禦性**。 我上面只是舉了乙個例子,一般我們都會和伺服器端約定好資料格式以及其他細節,而且大多數時候都會做一些保護,但我真正想強調的是客戶端不崩潰一定優於客戶端依賴於伺服器端而不崩潰,盡可能避免受到外界的影響
在ios 9.0之後nsnotificationcenter不會對乙個dealloc的觀察者傳送訊息,所以如果應用最低版本是9.0,其實也不必每次都去移除通知,但如果需要支援更低的版本,還是一定要移除通知,否則會崩潰
kvo不移除監聽會導致奔潰,所以kvo的新增和移除必須成雙成對
記憶體洩露,最著名的是**和被**物件迴圈引用
以上都是我曾經遇到過的崩潰情況,當然還有很多我不知道的情況,畢竟技術是複雜的。我們或許可以使用一些工具來檢查或者避免崩潰,但我還是想強調平時對待**要更加嚴謹,對待負責的專案要更有責任感
iOS開發中,iOS10許可權崩潰問題
意思是說 你需要在info.plist檔案 新增乙個 nscontactsusagedescription 的key,value新增乙個描述。1,在專案中找到info.plist檔案,右擊有個 open as,以source code 的形式開啟 2,分別複製 以下 value 和key,key 一...
iOS開發 for in 可變陣列 崩潰
一 執行下面 會發生什麼?什麼解決?nsmutablearray array nsmutablearray arraywithobjects 122 333 444 nil for nsstring string in array 答 會崩潰,提示nsgenericexception異常。出現下面的...
IOS崩潰日誌
1.普通崩潰日誌 參考 1 程序資訊 incident identifier 30e46451 53fd 4965 896a 457fc11ad05f 崩潰報告的唯一識別符號 是與裝置標識相對應的唯一鍵值。雖然它不是真正的裝置識別符號,但也是乙個非常有用的情報 如果你看到100個崩潰日誌的crash...