1. 程式人生 > >IOS程式設計開發中的問題小結(一)

IOS程式設計開發中的問題小結(一)


        做了一段時間的IOS開發,在開發過程中遇到了一些問題,不一定具有代表性,只是作為個人開發學習過程中的一個小結吧。

        1.關於蘋果系統對於應用系統啟動時間的限制

        我們知道,iOS APP的最長啟動時間不得超過15秒。如果超過了這個限制,APP會被App Store拒之門外。但是,有時候你也會發現通過了App Store稽核的APP也會因為啟動時間過長被系統殺掉,為什麼呢?有時候你用xcode連線執行時程式執行正常,但斷開xcode執行時程式也會因此被系統殺掉,又是為什麼呢?

        對於第一個問題,很有可能是因為你的初始化操作裡面包含了需要網路迴應的操作,如果網路沒有迴應,或是迴應超時,都會導致程式被終結。而App Store稽核時不可能考慮所有網路的問題。還有可能是因為蘋果稽核測試時只是重點稽核該應用在新機器、新版本下的執行情況,並不關注老系統,這就可能導致新機器新系統的啟動時間在15秒內,但對於老系統,老機器就超出了這個限制。所以,我們在測試時要儘可能的覆蓋測試。  

       所以我們在程式初始化啟動時應儘量少做操作或不做操作,如果在載入根檢視時確實要進行某些操作,可以將操作放在viewDidAppear中進行。     

        對於第二個問題,iPhone的系統在程式啟動時使用一個看門狗定時器,一旦發現程式花費太長的時間用來初始化啟動程式,系統會終結程式,當xcode啟動程式時,看門狗定時器會因為xcode在attach到debugger上而失效。

       2.關於蘋果系統對於應用程式記憶體使用的限制

       一般來說,對於不同硬體配置的機型,具有不同的記憶體使用限制。而且某一程式能夠使用的記憶體大小,也與當前系統的可能記憶體有直接關係。在系統的應用程式開啟過多時,可能此應用程式就會收到系統的記憶體警告。Apple也沒有說自己的記憶體管理規則,也不告訴你iOS系統在執行時所佔的空間、後臺保留程式的記憶體保有量,App執行時,並不是一定要把資源全部載入到記憶體,App執行時真正在記憶體中佔的空間是動態的,它能夠使用的記憶體也是動態。根據開發經驗來說,應用程式的動態開闢的記憶體不要超過20M

 ,這只是個經驗值,並不是說應用程式記憶體使用超過了20M就一定會收到記憶體警告或崩潰。     

        3.關於應用程式閃退的問題

        對於應用程式閃退的原因,網上說了很多,這裡整理了下。

       ①操作了不該操作的物件,野指標之類的。
       ②對記憶體警告處理不當。
       ③主執行緒UI長時間卡死,被系統殺掉。
       ④程式內部異常邏輯沒處理好。
       ⑤sdk版本差異沒處理好。

       ⑥在新 iOS 上正常的應用,到了老版本 iOS 上秒退最常見原因是系統動態連結庫或Framework無法找到。這種情況通常是由於 App 引用了一個新版作業系統裡的動態庫(或者某動態庫的新版本)或只有新 iOS 支援的 Framework,而又沒有對老系統進行測試,於是當 App 執行在老系統上時便由於找不到而秒退。解決辦法是等開發人員發現這個問題後升級程式,或由使用者自行升級其作業系統

       ⑦程式在升級時,修改了本地儲存的資料結構,但是對使用者既存的舊資料沒有做好升級,結果導致初始化時因為無法正確讀取使用者資料而秒退。這類問題通常只需刪除程式後重新安裝一遍就能解決。但缺點是使用者的既存資料會丟失——就算有備份可能也無濟於事,因為備份下來的舊資料還是無法被正確升級。

       ⑧還有一類秒退或是用到 App 裡某個功能後必退的原因,是開發時用到了只有新版作業系統才支援的某個方法,而又沒有對該方法是否存在於老系統中做出判斷。例如程式啟動時用到了 Game Center,而沒有判斷使用者的機器是否支援 Game Center,於是就秒退了。

       4.應用程式崩潰的一個特例

       筆者在程式開發的過程中,曾經遇到過這樣一個崩潰情況:應用程式在系統記憶體使用過多時(如開了很多的應用程式),當程式從子檢視返回父檢視時,點選父檢視上某一UI控制元件時,程式崩潰,這種崩潰的情況還不容易復現。最開始以為是記憶體洩露導致的,使用Analyze還有Profile中的Leaks進行分析,排除了所有的記憶體洩露點還是沒解決。後來才知道,原來是didReceiveMemoryWarning函數出現了問題。didReceiveMemoryWarning是在應用程式收到記憶體警告時會自動執行,回收記憶體。在didReceiveMemoryWarning中,對於當前頁面的資源進行了釋放。當從子檢視返回時,雖然父檢視依然予以了顯示,但這些控制元件資源已經釋放了,點選就會造成崩潰。

       5.關於應用程式在系統處於超頻時的問題

       筆者在開發過程中遇到過這樣的情況,應用程式系統在跳到某一頁面時,該頁面上的按鈕控制元件可以正常點選,但是TextField等控制元件的點選後要等很長一段時間後才能響應,但是程式並沒有崩潰。後來在Show the Debug Navigator中觀察才知道,程式此時處於超頻狀態,導致系統無法及時響應。經過排查,發現是使用了系統的延時等待函式dispatch_after,使得系統CPU使用率一下就上去了。

       6.關於C/C++,Objective-C混合程式設計的問題。

       在做C/C++,Objective-C混合程式設計時曾遇到過這樣一個問題:程式出現了incorrect checksum for freed object - object was probably modified after being freed的錯誤。從字面上的意思是物件在釋放後又被修改了。解決此問題的思路如下:首先,通過設定“殭屍”斷點的方式找到了出錯的地方,但是找到的是在函式執行的末尾,並沒有說明是哪個物件出現了問題;沒辦法,只能進行第二步,將該函式所有的物件釋放語句選擇性遮蔽掉,檢查具體是哪個物件的問題,但可惜遮蔽掉該函式所有物件釋放語句還是報錯;所以將這種檢查方式延續到該函式的子函式中,終於找到了出現問題的物件,發現是NSDateFormatter物件(後來才知道,這個物件會很影響應用程式的效能,要儘量避免使用,不過,這和此處的問題無關)。我是在C++類函式中建立初始化了這個物件,並呼叫了物件的方法,但沒有釋放,因為整個工程設定為了ARC,不能使用release,但問題可能就出在系統的自動釋放池釋放該物件的時機不對上面了。後來,我在OC物件的函式中建立這個物件獲取到系統時間,然後通過全域性變數的方式傳到了C++類函式中使用解決了這一問題。