天天看點

iOS應用啟動速度

​​http://ke.indiebros.com/2012/08/20/ios-app-launch-time-optimization/​​

很多app的開發者都不重視app的啟動速度,這對于碎片化使用情景的使用者來說,簡直是災難。

iOS應用的啟動速度

應用啟動時,會播放一個放大的動畫。iPhone上是400ms,iPad上是500ms。最理想的啟動速度是,在播放完動畫後,使用者就可以使用。

如果應用啟動過慢,使用者就會放棄使用,甚至永遠都不再回來。抛開代碼不談,如果抱着PC端遊和單機遊戲的思維,在遊戲啟動時強加公司Logo,啟動動畫,并且使用者不可跳過,也會使使用者的成功使用率大大降低。

iOS系統的“看門狗"

為了防止一個應用占用過多的系統資源,開發iOS的蘋果工程師門設計了一個“看門狗”的機制。在不同的場景下,“看門狗”會監測應用的性能。如果超出了該場景所規定的運作時間,“看門狗”就會強制終結這個應用的程序。開發者們在crashlog裡面,會看到諸如​

​0x8badf00d​

​這樣的錯誤代碼(“看門狗”吃了壞的食物,它很不高興)。

場景 “看門狗”逾時時間
啟動 20秒
恢複運作 10秒
懸挂程序 10秒
退出應用 6秒
背景運作 10分鐘

值得注意的是,Xcode在Debug的時候,會禁止“看門狗”。

如何測試啟動時間

兩種方法:一種使用NSLog,另外一種使用Time Profiler。

  • 使用NSLog
1 CFAbsoluteTime StartTime;
 2 int main(int argc, char **argv) {
 3      StartTime = CFAbsoluteTimeGetCurrent();
 4      // ...
 5 }
 6 
 7 - (void)applicationDidFinishLaunching:(UIApplication *)app {
 8      dispatch_async(dispatch_get_main_queue(), ^{
 9         NSLog(@"Launched in %f sec", CFAbsoluteTimeGetCurrent() - StartTime);
10      });
11      // ...
12  }      
  • 使用Time Profiler
  • Instruments->Time Profiler
  • Profile你的app
  • 切換到CPU strategy view,找到你的app啟動的第一幀
  • 搜尋​

    ​-[UIApplication _reportAppLaunchFinished]​

  • 找到包含​

    ​-[UIApplication _reportAppLaunchFinished]​

    ​的最後一幀,即可計算出啟動時間

iOS App啟動過程

  • 連結并加載Framework和static lib
  • UIKit初始化
  • 應用程式callback
  • 第一個Core Animation transaction

連結并加載Framework及static lib時需要注意:

  • 每個Framework都會增加啟動時間和占用的記憶體
  • 不必要的Framework,不要連結
  • 必要的Framework,不要票房為Optional
  • 隻在使用在Deployment Target之後釋出的Framework時,才使用Optional(比如你的Deployment Target是iOS 3.0,需要連結StoreKit的時候)
  • 避免建立全局的C++對象

初始化UIKit時需要注意:

  • 字型、狀态欄、user defaults、main nib會被初始化
  • 保持main nib盡可能的小
  • User defaults本質上是一個plist檔案,儲存的資料是同時被反序列化的,不要在user defaults裡面儲存圖檔等大資料

應用程式的回調:

  • ​application:willFinishLaunchingWithOptions:​

  • 恢複應用程式的狀态
  • ​application:didFinishLaunchingWithOptions:​

我一直認為設計的本質是折衷。當你為了100ms的啟動速度優化歡欣不已,而無視那長達10秒的啟動動畫時,應該想想究竟什麼是應該做的。​

​做正确的事情比把事情做好更重要。​

有一天,公司的網絡出現的問題,所有的機器都不能通路外網了。突然我發現一直運作正常的iPad應用在啟動時經過較長時間的等待後就退出了。

第一反應:是不是對網絡通信的處理有問題,導緻程式崩潰?那就進入debug跟蹤一下吧。奇怪的是,在debug模式下,盡管啟動時間較長,但仍然能正常運作下去。(啟動時間長的原因是,啟動時需要通路伺服器,擷取資料,由于網絡有問題,時間就長了)

我一度懷疑是不是ios的bug,但我試了很多其他的應用,為什麼其他應用都能正常運作呢?

經過長時間的google,終于對這個問題的産生了解的越來越清楚了。(google是需要技巧的,不合适的關鍵字往往找不到想要的答案,不要放棄,多嘗試,要相信你不是第一個遇到這個問題的人)

原來,啟動時間太長,ios會認為應用不用正常啟動,是以把應用直接給退出了。并不是應用崩潰了。

那為什麼debug時沒有這個問題呢? 參見文檔: http://developer.apple.com/library/ios/#qa/qa2009/qa1592.html

如此看來,解決問題的辦法就是盡快的結束啟動過程。網絡通路通過線程解決,這樣就不會阻塞主線程的運作了。