一. iOS中常见文件

(一). Xcode6之前

  1. 创建项目,默认可以看见一个存放框架的文件夹

  2. info文件以工程文件名开头,如:第一个项目-Info.plist

  3. 项目中默认有一个PCH文件

(二). Xcode6之后(包括Xcode6)

  1. 创建项目,没有框架文件夹,使用时系统才去加载

  2. info文件不以工程文件名开头,如:Info.plist

  3. 项目中没有PCH文件

(三). Info.plist文件(项目配置文件)

  1. 作用:保存应用的信息,软件名称、版本号等等,相当于身份证

  2. Bundle name:程序名称,不能超过12个字节

  3. Bundle versions string, short:APP版本号

  4. Bundle identifier:APP项目唯一标识

  5. Bundle version:内部开发人员使用的版本号

  6. Main storyboard file base name:第一启动的storyboard文件

  7. 注意:图形化的Info.plist文件上面的KEY不是真实的KEY,要想看真实的KEY得看Info.plist文件的源码
    操作:Info.plist(选中后右键单击) -> Open As -> Source Code

  8. 代码查看版本号

NSDictionary *dicInfo = [NSBundle mainBundle].infoDictionary;NSLog(@"%@",dicInfo[@"CFBundleShortVersionString"]);

(四). PCH文件

PCH文件是一个头文件,能被项目中的其他所有源文件共享和访问

1. PCH文件的需求

一个宏或头文件等,很多文件都需要用到,怎么解决,搞个公用的头文件,同时导入这个头文件

2. 作用

(1). 存放一些公用的宏
(2). 存放一些公用头文件
(3). 管理日志的输出,自定义Log

3. 为什么要管理日志输出

因为日志输出非常耗性能,一般发布的时候不需要日志输出,只有调试的时候才需要

/*
...表示能接收任何参数
__VA_ARGS__ 表示左边...的参数会替代到右边NSLog中
*/#ifdef DEBUG // 调试阶段#define HMLog(...) NSLog(__VA_ARGS__)#else // 发布阶段#define HMLog(...)#endif

5. 注意

在PCH中写有关OC的语法,最好放在 #ifdef __OBJC__ 中,Xcode在每个OC文件中都定义了这个宏,也就意味着只有OC中的文件才拥有这些宏,避免了项目中有C文件的时候报错。

二. 程序的启动原理

(一). 程序的启动过程

  1. 打开程序

  2. 执行main函数

  3. 结束程序

(二). 执行main函数

int main(int argc, char * argv[]) {    @autoreleasepool {           // 第三个参数为nil时,默认是UIApplication类名
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
  1. UIApplicationMain函数的原型

UIKIT_EXTERN int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);

2. UIApplicationMain的底层实现

(1). 根据principalClassName提供的类名,创建一个UIApplication对象

a. UIApplication代表一个应用程序

b. UIApplication一般用来做一些应用级别的操作(app的提醒框,联网状态,打电话,打开网页,控制状态栏)

(2). 根据delegateClassName提供的类名,创建一个UIApplication的代理对象

a. 程序加载完毕时调用:application:didFinishLaunchingWithOptions:

b. 程序获取焦点时调用:applicationDidBecomeActive:

c. 程序进入后台时调用:applicationDidEnterBackground:

d. 程序失去焦点时调用:applicationWillResignActive:

e. 程序从后台回到前台时调用:applicationWillEnterForeground:

f. 内存警告,可能要终止程序时调用:applicationDidReceiveMemoryWarning:

g. 程序即将退出时调用:applicationWillTerminate:

(3). 开启一个主运行循环,它是保持程序一直在运行,并处理事件

(4). 加载Info.plist和启动图片,并且判断Info.plis有没有指定Main.storyboard,如果指定,就去加载

3. application隐藏状态栏

a. 设置Info.plist文件:添加健View controller-based status bar appearance,设置值为NO

b. 创建application

c. 调用隐藏状态栏方法

4. 补充:反射机制

反射机制好处:如果类名用字符串表示,即使类名写错,编译器不报错;如果通过反射机制,类名写错,编译器报错

NSString *class =  NSStringFromClass([AppDelegate class]);
AppDelegate *strClass = NSClassFromString(@"AppDelegate");

(三). 加载Main.storyboard

1. 加载Main.storyboard步骤

a. 创建窗口

b. 加载Main.storyboard,并且加载Main.storyboard指定的控制器

c. 把新的控制器作为窗口的根控制器,并让窗口显示出来

2. 窗口(UIWindow)

a. UIWindow是一个特殊的UIView,在一个APP中一般都会有一个UIWindows,但不仅只有一个,如:软键盘也是一个窗口

b. APP程序启动完毕后,创建的第一个视图控件是UIWindow,接着创建控制器的View,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上

c. 一个APP之所以能显示到屏幕上,完全是因为有UIWindow

d. UIScreen : 标识物理的屏幕,它连接着设备

e. UIWindow : 用于提供屏幕绘制支持的,提供了一些绘图的方法

f. UIView : 窗口上有很多View,是用于提供绘图操作的,把画好的View添加到窗口上,就可以显示;屏幕上的东西都是绘制上去的,刷新一遍相当于重新绘制一遍

g. 只有加载Main.storyboard的时候才创建窗口(这里说的加载是系统自动加载)

h. 如果是自己代码加载Main.storyboard,需要自己代码创建窗口

3. 补充

a. 如果把新创建的控制器的View用addSubview:方法直接添加到窗口上,不会有旋转功能

b.设置窗口的根控制器rootViewController,会自动把控制器的View添加到窗口

c. 查看主窗口:application.keyWindow

d. 显示窗口:self.window.hidden = NO;

e. 查看程序的所有窗口:application.Windows

4. addSubView和rootViewController的区别

a. 直接用addSubView,控制器会被释放,控制器就不能处理事件

b. 直接用addSubView,控制器的view不会自动旋转

c. 用rootViewController,控制器不会被释放,而且控制器的view会自动旋转

d. 旋转事件 -> UIApplication -> Window -> rootViewController ->旋转控制器的view

5. makeKeyAndVisible方法底层所做的事情

a. 把窗口设置成主窗口,如:application.keyWindow = self.window;

b. 显示窗口,如:self.window.hidden = NO;

c. 注意:虽然底层会做上面两步,但不一定是上面的代码

6. 窗口的层级

windowLevel: UIWindowLevelNormal < UIWindowLevelStatusBar < UIWindowLevelAlert

UIWindowLevelNormal : 默认窗口的层级

UIWindowLevelStatusBar : 状态栏、键盘

UIWindowLevelAlert :UIActionSheet,UIAlearView

把window的层级设置为UIWindowLevelAlert ,就会显示在最前面

相同层级的窗口,想让其中一个显示,可以用那个窗口的层级加上一个数

7. 代码模仿storyboard的加载

注:要习惯代码创建窗口和控制器,因为开发中很少用到storyboard直接开发,老项目中没有storyboard

 

// 创建窗口
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // 加载storyboard
// Main.storyboard文件名不用写后缀
// 当写nil时,系统默认[NSBundle mainBundle]
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; //创建控制器
//方式1:代码创建控制器
//UIViewController *vc = [[UIViewController alloc] init];
//vc.view.backgroundColor = [UIColor whiteColor]; //方式2:加载storyboard里面有箭头的控制器
//UIViewController *vc = [storyboard instantiateInitialViewController];
// 当加载storyboard里面的控制器,控制器所属哪个类,就是创建哪个类
//NSLog(@"%@",NSStringFromClass([vc class])); //方式3:storyboard里面有多个控制器,加载对应标识的控制器
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"B"]; //创建窗口的根控制器
self.window.rootViewController = vc; // 显示窗口
[self.window makeKeyAndVisible];

(四). 通过XIB创建控制器的view

1. 步骤

a. 创建一个控制器的类

b. 创建一个xib,并指定xib所描述的控制器,一个xib只能用来描述一个控制器,如果没有指定,就不能拖线指定控制器的view

注意:xib里可以有多个UIView,不能固定死

 

c. 拖线指定xib中哪个UIView是控制器的view

选中File`s Owner,右键单击后,在弹出的对话框上拖线

d. 代码加载xib中描述控制器的view

 //创建窗口
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // 方式一:明确initWithNibName:方法的两个参数
//UIViewController *vc = [[ViewController alloc] initWithNibName:@"View" bundle:[NSBundle mainBundle]];
// 方式二:initWithNibName:方法的两个参数,只明确第一个参数,省略第二个参数
// bundle写nil时,系统默认[NSBundle mainBundle]
//UIViewController *vc = [[ViewController alloc] initWithNibName:@"View" bundle:nil];
// 方式三:initWithNibName:方法的两个参数都省略
//UIViewController *vc = [[ViewController alloc] initWithNibName:nil bundle:nil];
// 方式四:调用init方法
UIViewController *vc = [[ViewController alloc] init]; // 设置窗口的根控制器
self.window.rootViewController = vc; // 设置程序的主窗口并显示窗口
[self.window makeKeyAndVisible];

2. 注意

只有控制器的init方法,底层才会调用initWithNibName:bundle:方法

3. view的创建

a. 如果重写loadView,就根据自定义的view创建view

b. 如果没有重写loadView,就去查看有没有storyboard,有storyboard,就根据storyboard里描述的view创建;

c. 如果没有storyboard,就去查看有没有指定的xib,有指定的xib,就根据xib里描述的view创建;

d. 如果没有指定的xib,即nibName为nil时,就查看有没有与xib的拥有者同名的xib,但优选查看没有Controller的xib,如果查不 到,就查看有没有与xib的拥有者完全同名的xib,如:xib的拥有者是ViewController,xib的文件名是View,就优先查看 View.xib,根据它描述的view创建;如果没有文件名为View的xib,就去查看有没有名字为ViewController的xib,如果有就 根据xib里描述的view创建

e. 如果以上的情况都没有,就创建一个空的View

4. 控制器的loadView方法

A. loadView的作用:自定义控制器的view,只要重写了这个方法,说明要自己创建view,就不会自动创建view

B. loadView什么时候调用:第一次使用view的时候调用,调用这个方法创建控制器的view。

C. loadView默认做法:如果storyboard描述了控制器的view,就会去加载storyboard的view

D. 注意:

a. 只要重写loadView方法,没有调用系统默认的做法,即不写[super loadView],就不会去加载storyboard或者xib来描述控制器的view

b. 如果重写loadView方法,并且指定了nibName,loadView默认的做法会去加载xib的view

c. 只要重写loadView方法,没有指定nibName,就不会自动去加载和控制器同名的xib

d. 在重写loadView时,没有给self.view创建view,就使用self.view,会造成死循环

e. 如果是根控制器的view,自定义view的时候可以不设置尺寸,系统会自动设置;不是跟控制器就不行;可以用CGRctZeco表示,如:self.view = [[UIView alloc] initWithFrame: CGRctZeco];

f. 重写loadView方法时,不要写[super loadView];,因为重写该方法的目的是自定义view,重写了还要去加载storyboard里的view,
等于多此一举

5. xib和storyboard的区别

storyboard已经指定了控制器的view,不需要我们管,xib需要我们手动管理

 

6. 如何快速生成一个xib描述控制器的view

  1. 定义新的控制器的时候,勾选xib,会自动搞一个xib描述控制器的view

  2. 会自动生成一个和控制器同名的xib,并且里面设置好了

(五). 控制器的View

1. view的生命周期

只要是View开头的都是View的生命周期方法

 

loadView:第一次使用view的时候调用

viewDidLoad:控制器的view加载完成的时候调用

viewWillAppear:控制器的view即将显示的时候调用

viewDidAppear:控制器的view完全显示的时候调用

viewWillDisappear:控制器的view即将消失的时候调用

viewDidDisappear:控制器的view完全消失的时候调用

viewWillLayoutSubviews:控制器的view即将布局的时候调用

viewDidLayoutSubviews:控制器的view完全布局的时候调用

viewWillUnload:控制器的view即将销毁

viewDidUnload:控制器的view完全销毁

2. 内存警告处理

a. 处理过程

有内存警告 -> 调用didReceiveMemoryWarning方法 -> 判断控制器的View存不

存在 ->

存在就判断能不能被释放(判断是不是正在显示在界面上) -> 能释放就调用ViewWillUnload ->

完全释放后就调用ViewDidUnload

b. 注意

内存警告处理时,ViewWillUnload和ViewDidUnload不一定被调用,因为这是系统自动判断的

iOS常见文件及程序的启动原理的更多相关文章

  1. iOS的常见文件及程序的启动原理

    一. iOS中常见文件 (一). Xcode6之前 创建项目,默认可以看见一个存放框架的文件夹 info文件以工程文件名开头,如:第一个项目-Info.plist 项目中默认有一个PCH文件 (二). ...

  2. 【原】iOS学习之应用程序的启动原理

    最近看视频了解了一下应用程序的启动原理,这里就做一个博客和大家分享一下,相互讨论,如果有什么补充或不同的意见可以提出来! 1.程序入口 众所周知,一个应用程序的入口一般是一个 main 函数,iOS也 ...

  3. iOS程序的启动原理

    一.在一些老的项目中,有很多不是通过代码添加窗口和跟控制器.是通过设置MainInterface(设置最主要的xib),在xib中通过图形化的操作设置应用程序的代理->设置窗口->设置根控 ...

  4. Android启动原理剖析

    我们知道Android是以一个Activity为单位的,可是我们并没有看到一个Activity是怎么開始启动的. 今天我 们就从Android的源码開始讲吧. ActivityThread: Andr ...

  5. iOS app 程序启动原理

    iOS app 程序启动原理 Info.plist: 常见设置     建立一个工程后,会在Supporting files文件夹下看到一个"工程名-Info.plist"的文件, ...

  6. iOS开发——UI进阶篇(七)程序启动原理、打电话、发短信

    一.Info.plist常见的设置 1.建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 ...

  7. Info.plist和pch文件的作用,UIApplication,iOS程序的启动过程,AppDelegate 方法解释,UIWindow,生命周期方法

    Info.plist常见的设置 建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 注:在旧 ...

  8. iOS基础 - iOS程序启动原理

    一.UIApplicationMain 在main.m的main函数中执行了UIApplicationMain这个方法,这是ios程序的入口点 int UIApplicationMain(int ar ...

  9. iOS程序启动原理---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...

随机推荐

  1. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.5.1

    Show that the inner product $$\bex \sef{x_1\wedge \cdots \wedge x_k,y_1\wedge \cdots\wedge y_k} \eex ...

  2. Initializing nested object properties z

    public class Employee { public Employee() { this.Insurance = new Insurance(); } // Perhaps another c ...

  3. 《Oracle Database 12c DBA指南》第二章 - 安装Oracle和创建数据库(2.1 安装Oracle数据库软件和创建数据库概览)

    当前关于12c的中文资料比较少,本人将关于DBA的一部分官方文档翻译为中文,很多地方为了帮助中国网友看懂文章,没有按照原文句式翻译,翻译不足之处难免,望多多指正. 2.1 安装Oracle数据库软件和 ...

  4. 判断A树是否包含B树结构

    题目:输入两棵二叉树A和B,判断B是不是A的子结构 分析:根据数的遍历方法,首先想到的是采用递归的方式要更简单些,树A从根节点进行遍历,首先判断与B的根节点值是否相等,如果相等则进行递归遍历验证,否则 ...

  5. jenkins api调用

    在使用jenkins的时候,有时候需要其他外部调用,下面是调用方法,不定期更新 job调用 使用user和password: curl -X POST "jobPath/buildWithP ...

  6. SystemParametersInfo

    Python的模块pywin32中的win32gui.SystemParametersInfo()函数 在使用win32con.SPI_SETDESKWALLPAPER设置Wallpaper时,其第二 ...

  7. Hubot Slack CoffeeScript

    公司买了一台Mac Pro,为了物尽其用,研究了半天把hubot-slack装好了,然后又花了点时间学习CoffeeScript(照着例子写也足够了).用slack来发版本还是很爽的.

  8. 可以使用Markdown了?

    园子果然领先 1.标题类 一级标题 二级标题 三级标题 四级 六级 怎么可以用#号?上传上去看看 2.换行 第一行 换一行 在换一行 3.多个下划线 the_odd_egg odd 斜体用星号 4.删 ...

  9. Hadoop,HBase,Zookeeper源码编译并导入eclipse

    基本理念:尽可能的参考官方英文文档 Hadoop:  http://wiki.apache.org/hadoop/FrontPage HBase:  http://hbase.apache.org/b ...

  10. hdoj 1856 More is better【求树的节点数】

    More is better Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 327680/102400 K (Java/Others) ...