哈喽,很久不见。最近处于心情低迷期就没怎么来更新文章了。性能优化
在下也算是个半路出家的代码家,从以前的文章更新到如今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时间:能不作数据处理尽量不作,将耗时任务交由线程处理!
汇报完毕,咱们明天见