一步一步分析新建App启动过程

IOS温故而知新(一)  一步一步分析新建App启动过程

笔者接触IOS大概半年的时间,可以说能够开发App,但是又有很多不足的地方,因此打算写一些技术文章,能够达到温故而知新的效果,难免会有错误或者遗漏,也希望各位看官不吝指教。另外宣传一下刚建立的群“IOS菜鸟到高手之路”,312747764,欢迎希望交流分享的人加入。

1、IOS系统的简单说明
IOS与Mac OS X以及安卓一样都属于类UINX系统,然而熟悉类UNIX系统的人可能会失望的是,个人开发的App会进入类似chroot的状态,被操作系统隔离开来,这就是所谓的沙盒,无法知晓其他应用程序,也无法访问文件系统,无法直接使用硬件——可以通过IOS提供的框架进行申请访问,mmap也在底层被修改以防止直接写内存页面的操作。如果要在IOS下进行开发,还是老老实实的使用IOS提供的框架吧。

2、建立一个新的App
环境:Xcode6
使用Xcode建立一个新的工程New Project,选择默认的Single View Application,然后命名,一个新的App就诞生了,可以直接运行在模拟器,如果有开发者账号,也可以配置后直接连接机器,新机器的通用签名,点击Fix Issue即可,Xcode会搞定剩余的事情,这里就不细说了。

3、App的开始
尽管已经建立了一个App,对于它的执行过程我们还是一无所知,让我们首先找到它的入口,Support Files/main.m

?


1

        return UIApplicationMain(argc, argv, nilNSStringFromClass([AppDelegate class]))

众所周知,main函数是C语言程序的入口,同样的它也是Objective C的入口
从直观的角度猜测,UIApplicationMain如果返回,则程序会结束,所以它会在结束时返回或者永远不会返回,而传入的可控参数则是最后一个参数,是一个类的名字。
实际上,UIApplicationMain函数永远不会返回,它负责对于建立程序执行所需要的类,进行初始化,并使程序进入事件等待的循环中,而最后一个参数则指明了程序执行所需的代理类。

4、AppDelegate 
让我们首先找到文件AppDelegate.m
除了修改代理协议的类,main.m几乎没有什么可以改动的地方,AppDelegate才是开发者大展拳脚的地方,几乎一切对于程序的控制都始于这里,程序的初始化,状态的改变都需要在这里得到响应。
可能新建程序的你要迷茫了,尽管可以看到(void)applicationWillResignActive这种有关状态切换的函数,明明什么代码都没有,界面又是如何显示的?

5、UIWindow
为了搞清界面显示的问题,首先要知道IOS进行显示,需要一个UIWindow类,来管理和定位各种视图(Views)。
为了测试,我们加入如下代码

?


1

2

3

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    NSLog(“window is %@”, self.window)

}

执行后,显示
window is <UIWindow: 0x7f9a29532380; frame = (0 0; 375 667); hidden = YES; gestureRecognizers = <NSArray: 0x7f9a2952dab0>; layer = <UIWindowLayer: 0x7f9a2952f490>>
已经有值,可以推断,UIWindow在UIApplicationMain里面已经建立,那么问题来了,它是如何建立的?

6、Storyboard
在已经存在的文件中,最大的嫌疑就是它了,Main.storyboard,点击它我们可以很直观的发现,就是它在控制显示。Storyboard是IOS5以后推出的画板功能,可以比较方便的实现场景的转换和界面的布局,是一个便利的功能,相对的,有点不利于对于程序本身的理解。
然而到这里我们并没有搞清楚,UIApplicationMain是如何加载Storyboard的。

7、Info.plist
锁定最后的嫌疑人,就是它了。Info.plist可以看做是一个配置文件,它属于IOS bundle概念里必备的文件,可以通过man plist来查看格式,在IOS App中,可以直接将它看做一个字典。
在Info.plist中,可以找到:
“Main storyboard file base name”  String “Main”
在这里我们把“Main”改成”xx”, 试试看。
程序执行崩溃,不过不要慌张,看看结果

?


1

2

    3   UIKit                               0x0000000101170059 -[UIApplication _loadMainStoryboardFileNamed:bundle:] + 40

    4   UIKit                               0x000000010116f0cb -[UIApplication _runWithMainScene:transitionContext:completion:] + 1074

证明了正是UIApplication在之前加载了storyboard
删掉这个条目, 再启动,屏幕变成了黑屏
日志显示 window is (null)

8、手动添加window

?


1

2

3

4

5

6

7

8

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Override point for customization after application launch.

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; //全屏window

    self.window.backgroundColor = [UIColor whiteColor]; //白色背景

    [self.window makeKeyAndVisible]; //

 

    return YES;

}

启动,白屏幕,成功

9、总结
虽然废了一番功夫,不过弄清以后就比较简单了,App通过UIApplicationMain进入,根据Info.plist里的信息执行初始化(如果有Storyboard则加载),随后执行(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中的内容 ,执行完毕后,进行界面绘制,最后启动完毕,进入事件等待循环。

时间: 2024-12-11 14:33:30

一步一步分析新建App启动过程的相关文章

wxWidgets源码分析(1) - App启动过程

目录 APP启动过程 wxApp入口定义 wxApp实例化准备 wxApp的实例化 wxApp运行 总结 APP启动过程 本文主要介绍wxWidgets应用程序的启动过程,从app.cpp入手. wxApp入口定义 wxApp通过IMPLEMENT_APP宏注册App类,这个宏同时定义了入口,实现在wx/app.h文件中. // wx/app.h 文件中定义 #define IMPLEMENT_APP(app) wxIMPLEMENT_APP(app); // 可以忽略 wxIMPLEMENT_

linux内核学习之三 跟踪分析内核的启动过程

一   前期准备工作       1 搭建环境 1.1下载内核源代码并编译内核 创建目录,并进入该目录: 下载源码: 解压缩,并进入该目录:xz -d linux-3.18.6.tar.xz tar -xvf linux-3.18.6 cd  linux-3.18.6 选定x86架构的相关文件编译: 编译: 1.2 制作根文件系统 在工作目录下新建一个文件夹: mkdir rootfs 下载老师提供的资料:git clone https://github.com/mengning/menu.gi

安卓 应用app启动过程

韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha [email protected] 从用户点击 Launcher 上的 App 图标,到显示出 App 界面时主要发生的事情.知晓以下知识点. Android Process 的创建过程,以及 Activity Manager Service 是如何参与这个步骤,以及在其中扮演的角色? Android 中所谓的主线程是怎么回事?主线程是谁?又如何被创建的. Android 系统是如何节省进程创建开销的? 在 Android 中

android app启动过程(转)

Native进程的运行过程 一般程序的启动步骤,可以用下图描述.程序由内核加载分析,使用linker链接需要的共享库,然后从c运行库的入口开始执行. 通常,native进程是由shell或者init启动,启动的过程如下: Shell接收到命令,启动一个程序,此时shell首先会fork一个新的进程 新fork的进程,通过execve系统调用,陷入到内核中,内核检查和加载需要执行的二进制映像文件,检验其合法性及权限.通常用户态进程要启动一个新的程序(如shell),fork后,execve要紧跟着

NodeManager代码分析之NodeManager启动过程

1.NodeManager概述 NodeManager(NM)是YARN中每个节点上的代理,它管理Hadoop集群中单个计算节点,包括与ResourceManger保持通信,监督Container的生命周期管理,监控每个Container的资源使用(内存.CPU等)情况,追踪节点健康状况,管理日志和不同应用程序用到的附属服务. NodeManager整体架构: 2.NodeManager分析 接下来将按照启动NodeManager时代码执行的顺序为主线进行代码分析. 2.1 main函数 打印N

Netty源码分析之客户端启动过程

一.先来看一下客户端示例代码. 1 public class NettyClientTest { 2 public void connect(int port, String host) throws Exception { 3 EventLoopGroup group = new NioEventLoopGroup();//与服务端不同,客户端只需要一个IO线程组 4 5 try { 6 Bootstrap b = new Bootstrap(); 7 b.group(group) 8 .op

linux系统的启动过程简要分析

接触linux系统运维已经好几年了,常常被问到linux系统启动流程问题,刚好今天有空来梳理下这个过程:一般来说,所有的操作系统的启动流程基本就是: 总的来说,linux系统启动流程可以简单总结为以下几步:1)开机BIOS自检,加载硬盘.2)读取MBR,进行MBR引导.3)grub引导菜单(Boot Loader).4)加载内核kernel.5)启动init进程,依据inittab文件设定运行级别6)init进程,执行rc.sysinit文件.7)启动内核模块,执行不同级别的脚本程序.8)执行/

Netty源码分析之服务启动

本节主要分析server的启动过程. Netty是基于Nio实现的,所以也离不开selector.serverSocketChannel.socketChannel和selectKey等,只不过Netty把这些实现都封装在了底层. 从示例可以看出,一切从ServerBootstrap开始. ServerBootstrap实例中需要两个NioEventLoopGroup实例,分别为boss和work,有不同的分工:1. boss负责请求的accept操作.2. work负责请求的read.writ

你所不知道的SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)

前言 本篇主要是上一篇文章的补充篇,上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和解决方法,可点击查看,我们此篇主要介绍的是SQL Server启动过程中关于用户数据库加载的流程,并且根据加载过程中所遇到的一系列问题提供解决方案. 其实SQL Server作为微软的一款优秀RDBMS,它启动的过程中,本身所带的那些系统库发生问题的情况相对还是很少的,我们在平常使用中,出问题的大部分集中于我们自己建立的用户数据库. 而且,相对于侧重面而言,其实我们更关注的是我们自己建立的用户数