app的启动

前言

本篇文章讲解ios的应用程序的启动

应用程序的加载

点击一个app

首先,我们在手机上点击一个app图标

内核初始化

  • 操作系统收到启动app的消息后,会调用内核代码初始化内存空间,为app创建进程
  • 然后操作系统通过系统调用读取并解析app的可执行文件
  • 然后操作系统的动态链接器根据app的可执行文件的符号表去加载app运行依赖的动态库,或者叫共享库,并与符号表进行绑定,如果动态库已经加载过的话就直接绑定就行了,因为很多动态库是app共享的,可能在内存常驻。
  • 经过动态绑定以后,app的所有可执行代码和数据都已经准备就绪了,这个时候操作系统为app分配堆栈空间,拷贝代码和数据到内存等一系列操作
  • 然后确定程序启动的内存位置,开始执行具体的二进制指令

从开始到main函数

代码指令并不是从main函数开始执行的,在main函数之前还有一系类的关于代码的初始化操作,比如:

  • runtime运行时初始化。
  • 全局变量的初始化

main

int main(int argc, char * argv[]) {NSString * appDelegateClassName;@autoreleasepool {// Setup code that might create autoreleased objects goes here.appDelegateClassName = NSStringFromClass([AppDelegate class]);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

上面代码是一个main函数的执行代码,一般我们不需要修改这个函数中的代码,main函数主要的操作就是执行函数UIApplicationMain,该函数的原型如下:

// argc、argv:直接传递给UIApplicationMain进行相关处理即可
// principalClassName:指定应用程序类名(app的象征)
// 	该类必须是UIApplication(或子类)。
// 	如果为nil,则用UIApplication类作为默认值
// delegateClassName:指定应用程序的代理类,该类必须遵守UIApplicationDelegate协议
int UIApplicationMain(int argc, char * _Nullable argv[_Nonnull], NSString * _Nullable principalClassName, NSString * _Nullable delegateClassName);
  • 这也是第一步,执行UIApplicationMain
  • 第二步在UIApplicationMain内部执行,根据principalClassName创建UIApplication对象
  • 第三步根据delegateClassName创建一个delegate对象,并将该delegate对象赋值给UIApplication对象中的delegate属性。所以,我们的AppDelegate遵循UIApplicationDelegate协议
    @interface AppDelegate : UIResponder 	<UIApplicationDelegate>
    
  • 开启一个主运行循环,处理事件,可以让程序保持运行
  • 接下来,要加载info.plist,info.plist相当于我们应用程序的配置文件,在这里我们需要分开说明一下接下来的步骤啦,因为苹果公司在iOS 13的时候引入了多窗口的概念

IOS 13之前

  • 如果我们在info.plist设置了Launch screen interface file base name,程序会先加载Launch screen界面,这是个启动界面
  • 如果我们在info.plist设置了Main storyboard file base name,程序会加载Main storyboard界面,该文件中保存了我们app的Root View Controller,否则直接跳到下一步
  • 调用代理的application:didFinishLaunchingWithOptions:方法,一般情况下,如果我们没有创建主界面的话,会在这一步创建主界面,如果我们设置了Main storyboard file base name,然后又在该函数内创建了一个新界面,新界面会覆盖之前的界面。
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    

在IOS 13之前,应用程序的状态监听都是通过UIApplicationDelegate协议实现的,下面列出常用的UIApplicationDelegate协议。

UIApplicationDelegate协议
// 该方法是程序启动,但还没进入状态保存时执行。
// 该方法在启动界面之后执行
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(nullable NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions API_AVAILABLE(ios(6.0));// 该方法是程序启动基本完成,准备开始运行时执行。
// 该方法在启动界面之后执行,一般需要在该方法内创建主界面
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions API_AVAILABLE(ios(3.0));// 该方法是当程序将要进入非活动状态时执行,在此期间,应用程序不接收消息或事件,比如按下Home键或者来电话了。
- (void)applicationWillResignActive:(UIApplication *)application// 该方法是当程序已经进入后台时执行
- (void)applicationDidEnterBackground:(UIApplication *)application// 该方法是当程序将要进入前台时执行
- (void)applicationWillEnterForeground:(UIApplication *)application// 该方法是当程序进入活动状态时执行
- (void)applicationDidBecomeActive:(UIApplication *)application// 该方法是当程序程序将要退出时执行
- (void)applicationWillTerminate:(UIApplication *)application

IOS 13之后

如果我们设置ios程序的Mimimum Deployments的iOS版本小于13,程序依旧采用上述的UIApplicationDelegate协议,但是如果我们的iOS版本大于13,上述UIApplicationDelegate协议的

  • applicationWillResignActive
  • applicationDidEnterBackground
  • applicationWillEnterForeground
  • applicationDidBecomeActive

都不会执行,因为这几种状态被认为是scene的状态改变而不是应用程序的状态改变了。事实上,info.plist的加载都需要改变。
为了实现多窗口功能,苹果修改了使用多年的AppDelegate,把AppDelegate分为了两部分,AppDelegate和SceneDelegate,其中

  • AppDelegate处理应用程序状态的改变,比如应用程序的加载,退出
  • AppDelegate中新增对scene的支持
// 新建场景时会调用,返回场景配置信息
// 我们一般在这个里面记载Scene Configuration
// 下面是一个例子:return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options// 关闭场景时调用
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions
  • SceneDelegate处理场景的生命周期
// 配置UIWindow“窗口”并将其附加到所提供的UIWindowScene“场景”
// 如果在配置文件中配置了storyboard。UIWindow“窗口”将自动初始化并附加到场景
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions// 在系统释放场景时或者场景进入后台调用
- (void)sceneDidDisconnect:(UIScene *)scene// 当场景从非活动状态移动到活动状态时调用。
// 使用此方法可以重新启动场景处于非活动状态时暂停(或尚未启动)的任何任务。
- (void)sceneDidBecomeActive:(UIScene *)scene// 当场景将从活动状态移动到非活动状态时调用。
// 比如来电话或切入后台
- (void)sceneWillResignActive:(UIScene *)scene// 在场景从背景过渡到前景时调用。
- (void)sceneWillEnterForeground:(UIScene *)scene// 场景进入后台后调用
- (void)sceneDidEnterBackground:(UIScene *)scene

程序支持的场景需要在Info.plist中声明,由Info.plist->Application Scene Manifest->Scene Configuration->Application Session Role节点指定场景List,每一项包含以下节点:

  • Configuration Name:场景配置的唯一标识;
  • Delegate Class Name:实现UIWindowSceneDelegate代理类的名称;
  • Storyboard Name:Storyboard的名称(如果采用的是Storyboard方式实现UI),可选。

使用Scene Delegate之后,UIApplicationDelegate将不再持有UIWindow,它将转移至UIWindowSceneDelegate代理中

最后我们从加载配置文件开始重新梳理一下对于大于IOS13的启动过程

  • 首先调用AppDelegate中的configurationForConnectingSceneSession协议,该协议会返回默认加载场景的UISceneConfiguration*
  • Info.plist->Application Scene Manifest->Scene Configuration->Application Session Role中寻找场景列表,如果有,根据上一步返回的值匹配应该加载哪个场景,如果上一步返回nil,匹配列表中的第一个。如果列表为空,不加载场景,这时候应该是黑屏
  • 如果匹配到了场景信息
    • 如果包含storyboard,加载界面storyboard到UIWindow,执行下一步
    • 否则,继续执行下一步
  • 开始执行场景委托的willConnectToSession协议方法
  • 该协议中可以初始化并显示UIwinodw,如果不进行处理,UIWindow就用之前加载过的storyboard
  • 显示界面,完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/658078.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

apktool 简单快速 反编译apk获取图片资源

apktool:下载地址&#xff1a;iBotPeaches / Apktool / Downloads — Bitbucket把 myapp.apk 和 apktool_2.9.3.jar 放在同一文件夹&#xff0c;注意不要有中文路径 java -jar apktool_2.9.3.jar d -f myapp.apk -o myapp java -jar: java 执行jar命令 apktool_2.9.3.jar: a…

C语言实现的数组合并与排序程序

引言 在本篇博客中&#xff0c;我们将详细解析一段C语言代码&#xff0c;该代码实现了从用户处接收两个整数数组&#xff0c;将它们合并为一个数组后进行排序&#xff0c;并最终输出排序后的结果。这段代码主要涵盖了数组操作、数据输入、冒泡排序算法以及数据输出等核心编程概…

【涵子来信】——拆机,感想

大家好&#xff0c;我是涵子。 初中的第一个学期结束了&#xff0c;来临寒假。我在寒假做了一件有趣的事情&#xff1a;拆机&#xff0c;修手机。今天我来分享分享这件事情。 拆机 情况介绍 拆机对象&#xff1a; iPhone 6 Plus 情况&#xff1a; 电池健康度100%&#xff08…

按身高和体重排队(100%用例)C卷(JavaPythonC++Node.jsC语言)

某学校举行运动会,学生们按编号 (1 、 2 、 3 … n) 进行标识,现需要按照身高由低到高排列,对身高相同的人,按体重由轻到重排列;对于身高体重都相同的人,维持原有的编号顺序关系。请输出排列后的学生编号。 输入描述: 两个序列,每个序列由n个正整数组成(0 < n <…

Unity-WebGL

问题&#xff1a;提示gzip压缩报错解决&#xff1a;关闭打包的地方压缩&#xff0c;如下图问题&#xff1a;窗口未全屏解决&#xff1a;使用百分比画布替换固定尺寸画布 参考&#xff1a;新版Unity打包Webgl端进行屏幕自适应_unity webgl分辨率自适应-CSDN博客问题&#xff1a;…

GBASE数据库注册例程的权限

要在数据库中注册例程&#xff0c;被授权的用户将 SPL 命令包含在 CREATE FUNCTION 或 CREATE PROCEDURE 语句中。数据库服务器存储内部注册了的 SPL 例程。下列用户具 有在数据库中注册新的例程的资格&#xff1a; • 有 DBA 权限的任何用户可在 CREATE 语句中&#xff0c;使…

Springboot+Redis

首先前提我们要在自己的本机电脑或者服务器上安装一个redis的服务器 Redis配置 添加依赖: <!-- SpringBoot Boot Redis --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artif…

MicroPython核心:编译器

MicroPython编译过程包括以下步骤&#xff1a; 词法分析器将MicroPython程序文本流转换为标记。语法解释器将标记转换为抽象语法&#xff08;语法树&#xff09;。根据语法书输出字节码或本地代码。 本文以给MicroPython增加一个简单的语言特性为例来说明这一过程&#xff1a…

Linux Archcraft结合内网穿透实现SSH远程连接

文章目录 1. 本地SSH连接测试2. Archcraft安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定SSH公网地址6. SSH固定地址连接7. 结语 Archcraft是一个基于Arch Linux的Linux发行版&#xff0c;它使用最简主义的窗口管理器而不是功能齐全的桌面环境来提供图形化用户界面。…

JVM 内存模型

1 什么是 JVM 内存模型 JVM 需要使用计算机的内存&#xff0c;Java 程序运行中所处理的对象或者算法都会使用 JVM 的内 存空间&#xff0c;JVM 将内存区划分为 5 块&#xff0c;这样的结构称之为 JVM 内存模型。 2 JVM 为什么进行内存区域划分 随着对象数量的增加&#xff…

马哈鱼SQLFlow Lite的python版本

Gudu SQLFlow 是一款用来分析各种数据库的 SQL 语句和存储过程来获取复杂的数据血缘关系并进行可视化的工具。 Gudu SQLFlow Lite version for python 可以让 python 开发者把数据血缘分析和可视化能力快速集成到他们自己的 python 应用中。 Gudu SQLFlow Lite version for p…

Banana Pi BPI-R4开源路由器开发板快速上手用户手册,采用联发科MT7988芯片设计

介绍 Banana Pi BPI-R4 路由器板采用 MediaTek MT7988A (Filogic 880) 四核 ARM Corex-A73 设计&#xff0c;4GB DDR4 RAM&#xff0c;8GB eMMC&#xff0c;板载 128MB SPI-NAND 闪存&#xff0c;还有 2x 10Gbe SFP、4x Gbe 网络端口&#xff0c;带 USB3 .2端口&#xff0c;M.2…

计算机服务器中了halo勒索病毒怎么办,halo勒索病毒解密

在网络技术飞速发展的今天&#xff0c;越来越多的企业依赖数字化办公&#xff0c;为企业的生产生活提供了极大便利&#xff0c;但网络是一把双刃剑&#xff0c;网络安全威胁无处不在。近期&#xff0c;云天数据恢复中心接到很多企业的求助&#xff0c;企业的计算机服务器中了ha…

【Java】实现图书管理系统

文章目录 1. 设计背景2. 需求分析3. 设计思路4. 实现4.1 book包4.1.1 Book类4.1.2 BookList类(书架) 4.2 user包4.2.1 User 类4.2.2 AdminUser类&#xff08;管理员用户&#xff09;4.2.3 NormalUser类&#xff08;普通用户&#xff09; 4.3 operation包4.3.1 IOPeration接口4.…

Maven基本使用

Maven简介: Apache Maven 是一个项目管理和构建工具&#xff0c;它基于项目模型(POM)的概念&#xff0c;通过一小段描述信息来管理项目的构建&#xff0c;报告和文档 Maven的作用: (1&#xff09;项目搭建&#xff1b; &#xff08;2&#xff09;依赖管理&#xff1b; &#xf…

[力扣 Hot100]Day16 除自身以外数组的乘积

题目描述 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n…

Mac Monitor:一款为macOS安全研究量身定制的高级独立系统监控工具

关于Mac Monitor Mac Monitor是一款功能强大的高级独立系统安全监控工具&#xff0c;该工具专为macOS安全研究、恶意软件分类和系统故障排除而设计&#xff0c;主要基于Apple Endpoint Security&#xff08;ES&#xff09;实现其功能。 Mac Monitor能够收集各种类型的系统事件…

ASP.NET Core 过滤器 使用依赖项注入

过滤器是 ASP.NET Core 中的特殊组件&#xff0c;允许我们在请求管道的特定阶段控制请求的执行。这些过滤器在中间件执行后以及 MVC 中间件匹配路由并调用特定操作时发挥作用。 简而言之&#xff0c;过滤器提供了一种在操作级别自定义应用程序行为的方法。它们就像检查点&#…

科普类——设计一套无人驾驶遥操作系统的步骤、架构、软硬件需求(十一)

设计一套无人驾驶遥操作系统的步骤、架构、软硬件需求 **设计步骤**&#xff1a;**整体架构**&#xff1a;**所需硬件及提供商**&#xff1a;**人员需求**&#xff1a; 设计无人驾驶中的遥操作系统是一个跨学科的工程项目&#xff0c;涉及机械工程、电子工程、计算机科学和通信…

ARM与X86架构的区别与联系

文章目录 1.什么是CPU2.复杂指令集和精简指令集3.ARM架构与X86架构的比较3.1.制造工艺3.2 64位计算3.3 异构计算3.4 功耗 4.ARM和X86的发展现状Reference 1.什么是CPU 中央处理单元&#xff08;CPU&#xff09;主要由运算器、控制器、寄存器三部分组成&#xff0c;从字面意思看…