這種方法多是最容易的方法了。git
本文分析了拿到用戶的.crash文件以後,如何符合化crash文件的3種方法,分別有其適用場景,方法3適用於自動化crash文件的分析。github
1.NSThread:(兩種建立方式)面試
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];
[myThread start];
複製代碼
優勢:NSThread 比其餘兩個輕量級。 缺點:須要本身管理線程的生命週期,線程同步,線程同步時對數據的加鎖會有必定的系統開銷。算法
2.Cocoa Operationsql
NSOperationQueue*oprationQueue= [[NSOperationQueuealloc] init];
oprationQueueaddOperationWithBlock:^{
//這個block語句塊在子線程中執行
}
複製代碼
優勢:不須要關心線程管理,數據同步的事情。 Cocoa Operation 相關的類是 NSOperation ,NSOperationQueue。NSOperation是個抽象類,使用它必須用它的子類,能夠實現它或者使用它定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation。建立NSOperation子類的對象,把對象添加到NSOperationQueue隊列裏執行,咱們會把咱們的執行操做放在NSOperation中main函數中。數據庫
3.GCD Grand Central Dispatch (GCD)是Apple開發的一個多核編程的解決方法,GCD是一個替代諸如NSThread, NSOperationQueue, NSInvocationOperation等技術的很高效和強大的技術。它讓程序平行排隊的特定任務,根據可用的處理資源,安排他們在任何可用的處理器核心上執行任務,一個任務能夠是一個函數(function)或者是一個block。 dispatch queue分爲下面三種: private dispatch queues,同時只執行一個任務,一般用於同步訪問特定的資源或數據。 global dispatch queue,能夠併發地執行多個任務,可是執行完成的順序是隨機的。 Main dispatch queue 它是在應用程序主線程上執行任務的。 GCD 掃盲篇;編程
優勢: 1:一個類只被實例化一次,提供了對惟一實例的受控訪問。 2:節省系統資源 3:容許可變數目的實例。緩存
缺點: 1:一個類只有一個對象,可能形成責任太重,在必定程度上違背了「單一職責原則」。 2:因爲單利模式中沒有抽象層,所以單例類的擴展有很大的困難。 3:濫用單例將帶來一些負面問題,如爲了節省資源將數據庫鏈接池對象設計爲的單例類,可能會致使共享鏈接池對象的程序過多而出現鏈接池溢出;若是實例化的對象長時間不被利用,系統會認爲是垃圾而被回收,這將致使對象狀態的丟失。bash
參考此篇博客 裏面的信號量的解釋,Dispatch Semaphore 信號量 在項目中的應用:強制把異步任務轉換爲同步任務來方便進行單元測試網絡
①.先加載Main函數
②.在Main函數裏的 UIApplicationMain方法中,建立Application對象 建立Application的Delegate對象
③.建立主循環,代理對象開始監聽事件
④.啓動完畢會調用 didFinishLaunching方法,並在這個方法中建立UIWindow
⑤.設置UIWindow的根控制器是誰
⑥.若是有storyboard,會根據info.plist中找到應用程序的入口storyboard並加載箭頭所指的控制器
⑦.顯示窗口
本文考慮的時步驟③以後到步驟⑦結束時將要調用的方法
其中有AppDelegate,ViewController,MainView(控制器的View),ChildView(子控件的View)的18個方法
AppDelegate中的:
1.application:didFinishLaunchingWithOptions:
2.applicationDidBecomeActive:
ViewController中的:
3.loadView
4.viewDidLoad
5.load
6.initialize
7.viewWillAppear
8.viewWillLayoutSubviews
9.viewDidLayoutSubviews
10.viewDidAppear
MainView(控制器的View)中的:
11.initWithCoder(若是沒有storyboard就會調用initWithFrame,這裏兩種方法視爲一種)
12.awakeFromNib
13.layoutSubviews
14.drawRect
ChildView(子控件View)中的:
15.initWithCoder(若是沒有storyboard就會調用initWithFrame,這裏兩種方法視爲一種)
16.awakeFromNib
17.layoutSubviews
18.drawRect
那麼問題來了,不往下看你能夠把上面的十八個方法排個順序麼?
[圖片上傳失敗...(image-666d9e-1511926275309)]
+ (void)load; //這是應用程序啓動就會調用的方法,在這個方法裏寫的代碼最早調用
複製代碼
+ (void)initialize; //這個是須要用到本類時才調用,這個方法裏通常寫設置導航控制器的主題啊之類的,
//若是在後面的方法設置導航欄主題就晚了!(固然在上面的方法裏也能寫)
複製代碼
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
//這個方法裏面會建立UIWindow,設置根控制器並展示,
//好比某些應用程序要加載受權頁面也是在這加,也能夠設置觀察者,監聽到通知切換根控制器
複製代碼
ChildView - (instancetype)initWithCoder:(NSCoder *)aDecoder;
//這裏反正我是萬萬沒想到,childView的initwithcoder會在MainView的方法以前調用,
//父的都還沒出來,就先整子控件? 有了解比較透徹的博友懇請告訴我謝謝。
複製代碼
MainView - (instancetype)initWithCoder:(NSCoder *)aDecoder;
// 就是關於應用程序的數據存儲後的解檔操做。
複製代碼
MainView - (void)awakeFromNib;
//在這個方法裏設置view的背景等一系列普通操做,不要寫關於frame的還不許,
//在使用IB的時候纔會涉及到此方法的使用,當.nib文件被加載的時候,
//會發送一個awakeFromNib的消息到.nib文件中的每一個對象,
//每一個對象均可以定義本身的awakeFromNib函數來響應這個消息,執行一些必要的操做。
複製代碼
ChildView - (void)awakeFromNib
//子控件也有本方法,重寫父類的方法。基本用法同上
複製代碼
- (void)loadView;
//建立視圖的層次結構,這裏須要注意,
//在沒有建立控制器的view的狀況下不能直接寫 self.view 由於self.view的底層是:
if(_view == nil){
_view = [self loadView]
}
//因此這麼寫會直接形成死循環。
//若是重寫這個loadView方法裏面什麼都不寫,會顯示黑屏。
複製代碼
- (void)viewDidLoad;
//臥槽,這個方法是用的最多的方法,可是在以後的開發中就會發現愈來愈不靠譜,
//不少東西都還沒加載完畢,各類取值都不許確,不多在這裏面寫東西了。
//這裏只是把視圖元件加載完成
複製代碼
- (void)viewWillAppear:(BOOL)animated;
//視圖將要出現,這個方法用的很是多,好比若是要設置導航欄的setNavigationBarHiden:animate:
//就必需要在這裏寫,才能完美契合,不卡跳。 還有不少好比監聽屏幕旋轉啦,
//viewWillTransitionToSize:可能要在本方法裏再調一次,
//或者就是新到這個界面要reloadData或是自動下拉刷新等 都是寫在本方法裏
複製代碼
- (void)viewWillLayoutSubviews;
//視圖將要佈局子視圖,蘋果建議的設置界面佈局屬性的方法,
//這個方法和viewWillAppear裏,系統的底層都是沒有寫任何代碼的,也就是說這裏面不寫super 也是能夠的
複製代碼
MainView - (void)layoutSubviews;
//在這個方法裏通常設置子控件的frame,由於這裏至關因而佈局基本完成了,
//設置時取到的frame或者是self.bounds才最準,若是在awakeFromeNib裏寫會不許確 。
//還有這裏要切記千萬不能把super layoutSubviews忘了,可能最後都很難找到這個bug
複製代碼
- (void)viewDidLayoutSubviews;
//這個方法我也是玩玩沒想到,控制器的view的子控件尚未佈局好呢,怎麼這個控制器就已經說佈局所有完成了?
//那後邊的佈局就不等了? 有獨到看法的也懇請你告訴我,這其中蘋果的意思究竟是什麼。
複製代碼
ChildView - (void)layoutSubviews;
//控制器的子控件裏的子控件的佈局就在這裏寫了。
複製代碼
MainView - (void)drawRect:(CGRect)rect;
//由於默認全部額UI控件都是畫上去的,在這一步就是把全部的東西畫上去,
//有時候須要用到Quartz2D的知識的時候都是在這個方法裏話,但也是要注意別忘了寫super,
//否則系統本來的東西就都畫不上來了,這裏要建議儘量使用貝塞爾路徑畫圖形,
//由於系統默認的那個上下文畫法有時可能會內存泄露。drawRect方法只能在加載時調用一次,
//若是後面還須要調用,好比下載進度的圓弧,須要一直刷幀,
//就要使用setNeedsDisplay來定時屢次調用本方法
複製代碼
ChildView - (void)drawRect:(CGRect)rect;
//view的子控件內部的畫圖方法,有時能夠本身自定義label 中間帶個刪除線的(用來寫打折前的原價) 就是在這裏畫根線 。
複製代碼
- (void)viewDidAppear:(BOOL)animated;
//把上面的畫圖都畫完了,這裏就會顯示,視圖徹底加載完成。
//在這裏的操做可能就是設置頁面的一些動畫,或者是設置tableView,collectionView,
//QQ聊天頁面啥的滾動到底部scrollToIndexPath之類的代碼操做。
複製代碼
- (void)applicationDidBecomeActive:(UIApplication *)application;
//最後這是AppDelegate的應用程序獲取焦點方法,真正到了這裏,纔是全部東西所有加載完畢,應用程序整裝待發保持最佳狀態等待用戶操做。
//這個方法中通常會寫關於彈出鍵盤的方法,好比有的用戶登陸界面爲了更好的用戶體驗,
//就讓你在剛打開程序來到登陸界面的時候,光標的焦點就自動在帳號的文本框裏閃爍,
//也就是設置帳號文本框爲第一響應者。鍵盤在頁面加載完畢後從下方彈出,這種代碼通常就在本方法寫。
複製代碼
main()函數以前耗時的影響因素
main()函數以後耗時的影響因素
另外參考一下今日頭條的啓動優化方案
,針對於今日頭條這個App咱們能夠優化的點以下:
看門狗超時,在iOS上,它常常出如今執行一個同步網絡調用而阻塞主線程的狀況。所以,永遠不要進行同步網絡調用。
其實我以爲大可沒必要,自己反編譯成本就很大,代碼這麼多,一個個反編譯過來是在蛋疼,就算有僞代碼也須要理解,並且有些代碼就算有僞代碼也很難理解。
只要作好核心代碼,作好混淆就好了,好比涉及到密碼,核心算法。
通常這種問題的時候,面試官是想經過你講解你遇到的是什麼類型的問題,而後是怎麼解決的方案來判斷你的知識層面。值得注意的一點是,每每很多同窗在回答這道問題講如何解決的時候會說:首先經過Google、百度等搜索尋找解決方案,二、問羣裏。。。等等之類的答案。敲黑板啦~~注意啦,同窗們,人家要的不是這個答案好嗎?雖然你這麼答也不算是錯,只是理解有誤差,但起不到加分的結果。因此在面試以前,各位同窗應該好好的想一想這個問題的答案,固然每一個人遇到的難點都不大相同,涉及到的技術層面也不同,這也是這個問題的目的所在。
自行發揮吧!