APP启动过程

启动过程

一. 加载main函数,应用创建的第一个实例就是main函数中的UIApplicationMain实例

int main(int argc, char * argv[]) {
    
    @autoreleasepool {
        
        return UIApplicationMain(argc, argv, @"EOCApplication", NSStringFromClass([EOCAppDelegate class]));
        
    }
}

前两个参数:argc是命令行总的参数个数,argv是参数的数组,值得一提的是argv中第一个参数为app的路径+全名。

默认的第三个参数是nil,但是它实际传的是UIApplication,我们也可以写一个继承自UIApplication的类* EOCApplication来代替它。
NSStringFromClass方法是为了更安全,确保它是一个字符串类型,里面的类默认的是
AppDelegate,但是我们也可以写一个继承自UIResponder的类来代替,如果没有响应事件,也可以只是继承自NSObject。但是都必须遵循UIApplicationDelegate*代理方法,并且在.h文件中声明一个window属性,因为只有声明了window属性,控制器才能够加载window。

@interface EOCAppDelegate : NSObject
@property (strong, nonatomic) UIWindow *window;
@end

声明window属性,必须头文件要引入UIKit框架

二. 在main函数中创建Application对象 创建Application的Delegate对象。

三. 开启主事件循环runloop,AppDelegate代理对象开始监听系统事件(这是一个死循环,APP就是在这个循环里面监听并处理事件)。

四. 启动完毕会调用 didFinishLaunching方法,并在这个方法中创建并显示UIWindow

  • 设置UIWindow的根控制器是谁
  • 如果有storyboard,会根据info.plist中找到应用程序的入口storyboard并加载箭头所指的控制器
  • 显示窗口
runloop

runloop源码地址:地址
内部原理大概如下:

runloop  while (1){
    
    model while(1){
        切换的时候
        跳出去了
    }
}
隐藏状态栏

其中根视图最好固定,需要到登陆界面就跳转过去 在keyWindow上进行操作

windowLevel
UIWindowLevelAlert > UIWindowLevelStatusBar > UIWindowLevelNormal

其中隐藏状态栏,可以在didFinishLaunchingWithOptions方法中将keyWindow的层级设置为最高,因为状态栏其实也是一个window,这样就会覆盖掉状态栏,但是这样在整个APP里面都覆盖了

self.window.windowLevel = UIWindowLevelAlert;

当然也还有其他的方法隐藏状态栏

关于AppDelegate中的一些调用顺序
应用从前台进入后台
  • applicationWillResignActive
  • applicationDidEnterBackground

先失去焦点,再进入后台

从后台进入前台
  • applicationWillEnterForeground
  • applicationWillResignActive

先进入前台,再获取焦点。但是如果在进入前台的时候,你进行了大量的操作,比如说请求数据之类的,可能会引起卡顿,所以这个时候,可以另外开辟一个线程来做这些操作

关于项目拆分

可以使用分类或者类工厂来进行拆分

分类

为了使AppDelegate代理方法中的代码,更加方便阅读,可以按照业务创建几个AppDelegate的分类,然后再在主要的AppDelegate中进行调用。


APP启动过程_第1张图片
APP启动过程_第2张图片
类工厂
APP启动过程_第3张图片
APP启动过程_第4张图片
关于项目添加文件夹的时候

group :一般只在你的工程中是文件夹的形式,但是在本地的目录中还是以散乱的形式放在一起的,除非你是从外部以group的形式引用进来的。
folder: 只能作为资源,整个引用进项目,不能编译代码,也就是说,以folder形式引用进来的文件,不能被放在complie sources列表里面

启动时间

时间分为两个部分 T1(main前) + T2(main后), {T1:系统环境布局时间:创建进程,加载解析可执行文件(库加载,堆栈环境配置等等), T2:从main到第一个界面显示时间}
1、 库加载越多,启动越慢
2、 Objc类越多,越慢
3、 静态对象全局对象越多,启动越慢
4、 Objc的 +load越多,启动越慢
更能把控的:load 和 T2时间上进行优化 (前面三点随着项目越大,库和类就越多,我们不太好进行优化)

每个控制器的load加载在main函数运行之前,并且按照项目中文件配置先后顺序加载:


APP启动过程_第5张图片
.m文件资源的先后顺序.png

运行结果.png

我们尽可能少用控制器的load方法,已经在里面少做耗时的操作,如果有一些操作,可以用initialize方法代替

T2时间即是:从didFinishLaunchingWithOptions这个方法到显示出第一个界面的时间。所以我们尽可能在这个方法中少做操作,如果有耗时的操作移到子线程,也就是第一个界面出来之后再执行,可以做到优化

参考文章:
iOS 从main函数开始
iOS:App启动过程详解
iOS APP启动时所有方法的调用顺序分析

你可能感兴趣的:(APP启动过程)