哈嘍,很久不見。最近處於心情低迷期就沒怎麼來更新文章了。性能優化
在下也算是個半路出家的代碼家,從以前的文章更新到如今app
依然是仍是從基礎學起,萬物歸基礎!oop
因此從今天起天天回來更新彙報學習成果!!天天佈局
今天主要接觸的是Application相關的知識,包括App啓動原理,以及windos窗口控制以及Appdelegate的模塊優化等~ 性能
在咱們建立項目時,有個不起眼的main.m文件,裏頭只有一個方法,返回的也只有一個int對象。在我剛接觸IOS學識時,這一個不起眼的文件常常給我分類放在了一個文件夾裏。學習
具體有什麼用並無深究,可是我只知道的是沒回報錯都是從main文件裏傳出來的。優化
那麼main.m文件到底蘊含着什麼東西呢?spa
int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc , argv , nil , NSStringFromClass([Appdelegate clasee])); } }
Main文件中返回了一個UIApplicationMain對象,UIApplicationMain可厲害了線程
他幹了這麼幾件事情code
1.建立了 UIApplication 應用對象
2.建立了Application delegate(AppDelegate) 對象
3.創建了一個Event Loop (建立了Runloop對象而且開啓事件循環)
4.讀取info.plist文件
5.基於以上對象(UIApplication、AppDelegate、Runloop)建立一個windos
而且他自己就是一個死循環。爲何呢?
這得從事件循環,也就是Runloop對象提及。
蘋果的系統誇張的說,就是對Event loop的實現所創建的
當應用啓動時 - >開啓一個死循環Runloop
當頁面靜止時 -> Runloop處於wait狀態。
當觸發事件時 ->判斷事件來源(handle_msg),
根據來源處理觸發事件
1.定時器
2.GCD
3.Source1
處理結束後,繼續進入等待狀態或者應用結束退出循環。
簡要地說就是這麼一個周而復始的過程(具體能夠看第一篇關於RunLoop的白話文)
這裏可能有人會作一個小小的質疑,你說死循環就死循環?怎麼證實給咱們看?
也能夠
int main(int argc, char * argv[]) { @autoreleasepool { int back = UIApplicationMain(argc , argv , nil , NSStringFromClass([Appdelegate clasee])); NSLog(@"back == %d",back); return back; } }
這裏將UIApplicationMain拆分紅int對象而且打印他。
由於他是死循環的緣故因此NSLog並不會打印出來(不信你能夠試一下)。
講了那麼多關於ApplicationMain的東西,到底和代碼優化有什麼關係呢?
在說優化以前,還得講到的一個特殊的東西,UIWindos
衆所周知,在IOS的APP中windos一般只有一個,是一種特殊的UIView。
UIWindos有屬於自身的層級對象UIWindosLevel,UIWindosLevel的屬性有三,對應關係以下
UIWindosLevelAlert > UIWindosLevelStatusBar > UIWindosLevelNormal
雖然話說Windos一般只有一個,可是並非不可建立的,以上的屬性就是對於建立多個windos時,可用於控制層級顯示。
windos的做用呢,就是加載視圖,就相似app中裏面的電視機。少了他App什麼都不是。
那麼Windos怎麼建立呢? 這是application的子類的中的方法
static UIWindow *__xgWindows; @implementation AppDelegate (XGApp) - (void)startLoadAd { __xgWindows = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; __xgWindows.rootViewController = [XgADViewController new]; __xgWindows.windowLevel = UIWindowLevelAlert; [__xgWindows makeKeyAndVisible]; // [self performSelector:@selector(finishWindos) withObject:nil afterDelay:3]; NSLog(@"加載廣告頁"); }
刪除呢?只須要設置監聽對象,觸發方法將Windos設置爲nil便可。
如下是觸發方法。
- (void)finishWindos { NSLog(@"關閉Windos"); __xgWindows = nil; }
這裏咱們能夠根據代碼分析得知,咱們是能夠建立application的子類,來進行許多業務的處理。
上述例子咱們運用application的子類GgApplication建立了一個廣告頁,並在三秒銷燬了。在主線程的application didFinishLaunchingWithOptions~方法中
只用了一行代碼就解決了,通常來講在Application裏,由於Delegate的方法是啓動的一部分,因此代碼過於擁擠的話是會影響可視性以及啓動的速度的。
因此在可拆分的狀況下,業務儘量的多的拆分到子類中處理時有助於提升性能的!
在第一個視圖中,不相關的數據處理,均可以放到線程中處理(比較耗時的任務)*(省,市)數據加載
須要注意的是,邏輯必須的清晰。由於APPDelegate是啓動的一部分,稍有差錯是會影響總體運做流暢性的。
若是總體啓動過慢,APP開啓時間 ≥ 5s 時, 蘋果官方甚至會將整個App打回不容許上架。這是須要注意的。
關於啓動時間的優化,這邊給出一小部分公式但願能幫助到讀者。
啓動的時間 = T1 + T2
T1(Main方法執行前) 系統環境佈局時間:建立進程、加載分析可執行文件(庫加載、堆棧環境配置等)
T2(Main方法執行後):從Main方法執行到第一個界面顯示的時間
其中有如下四點是影響啓動速度的
1.庫加載越多,啓動越慢
2.Objc類越多,啓動越慢
3.靜態對象、全局對象越多、啓動越慢
4.Objc的 +load 越多,啓動越慢
在性能優化方面上更能人爲把控的:load 和T2時間
load: 是在加載過程當中,ViewController中的Load方法是自動執行在main方法前的,若是加載對象及方法過多,啓動也會隨之更慢。
因此能夠拆分的業務,儘量拆分處理!
T2時間:能不作數據處理儘量不作,將耗時任務交由線程處理!
彙報完畢,咱們明天見