您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
iOS常见文件及程序的启动原理
 
来源:SSIrreplaceable 发布于: 2017-3-29
  3248  次浏览      20
 

一. iOS中常见文件

(一). Xcode6之前

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

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

项目中默认有一个PCH文件

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

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

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

项目中没有PCH文件

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

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

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

Bundle versions string, short:APP版本号

Bundle identifier:APP项目唯一标识

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

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

注意:图形化的Info.plist文件上面的KEY不是真实的KEY,要想看真实的KEY得看Info.plist文件的源码

操作:Info.plist(选中后右键单击) -> Open As -> Source Code

代码查看版本号

NSDictionary *dicInfo = [NSBundle mainBundle].infoDictionary;

NSLog(@"%@",dicInfo[@"CFBundleShortVersionString"]);

;

(四). PCH文件

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

1. PCH文件的需求

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

2. 作用

(1). 存放一些公用的宏

(2). 存放一些公用头文件

(3). 管理日志的输出,自定义Log

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

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

#ifdef DEBUG // 调试阶段

#define HMLog(...) NSLog(__VA_ARGS__)

#else // 发布阶段

#define HMLog(...)

#endif

5. 注意

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

二. 程序的启动原理

(一). 程序的启动过程

打开程序

执行main函数

结束程序

(二). 执行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 *principalClassNam
e, 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

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

会自动生成一个和控制器同名的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不一定被调用,因为这是系统自动判断的。

   
3248 次浏览       20
 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...