iOS开发UI篇之16程序启动原理和UIApplication
iOS 开发 UI 篇 — 程序启动原理和 UIApplication
一、 UIApplication
1. 简单介绍
( 1 ) UIApplication 对象是应用程序的象征,一个 UIApplication 对象就代表一个应用程序。
( 2 )每一个应用都有自己的 UIApplication 对象,而且是单例的,如果试图在程序中新建一个 UIApplication 对象,那么将报错提示。
( 3 )通过 [UIApplicationsharedApplication] 可以获得这个单例对象
( 4 ) 一个 iOS 程序启动后创建的第一个对象就是 UIApplication 对象,且只有一个(通过代码获取两个 UIApplication 对象,打印地址可以看出地址是相同的)。
( 5 )利用 UIApplication 对象,能进行一些应用级别的操作
2. 应用级别的操作示例:
1 )设置应用程序图标右上角的红色提醒数字(如 QQ 消息的时候,图标上面会显示 1 , 2 , 3 条新信息等。)
@property(nonatomic) NSInteger applicationIconBadgeNumber;
代码实现和效果:
- ( IBAction )changeAppNum {
//错误,只能有一个唯一的UIApplication对象,不能再进行创建
// UIApplication*app=[[UIApplication alloc]init];
UIApplication *app = [ UIApplication sharedApplication ];
// 0代表清除图标右上角的数字
app. applicationIconBadgeNumber = 20 ;
}
2 )设置联网指示器的可见性
@property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
代码和效果 :
//设置指示器的联网动画
app. networkActivityIndicatorVisible = YES ;
3 )管理状态栏
从 iOS7 开始,系统提供了 2 种管理状态栏的方式
a. 通过 UIViewController 管理(每一个 UIViewController 都可以拥有自己不同的状态栏) .
在 iOS7 中,默认情况下,状态栏都是由 UIViewController 管理的, UIViewController 实现下列方法就可以轻松管理状态栏的可见性和样式
状态栏的样式 -(UIStatusBarStyle)preferredStatusBarStyle;
状态栏的可见性 -(BOOL)prefersStatusBarHidden;
#pragma mark-设置状态栏的样式
-(UIStatusBarStyle)preferredStatusBarStyle
{
//设置为白色
//return UIStatusBarStyleLightContent;
//默认为黑色
return UIStatusBarStyleDefault;
}
#pragma mark-设置状态栏是否隐藏(否)
-( BOOL )prefersStatusBarHidden
{
return NO ;
}
}
b. 通过 UIApplication 管理(一个应用程序的状态栏都由它统一管理)
如果想利用 UIApplication 来管理状态栏,首先得修改 Info.plist 的设置
代码:
UIApplication *app=[UIApplication sharedApplication];
app. applicationIconBadgeNumber = 123 ;
//设置指示器的联网动画
app. networkActivityIndicatorVisible = YES ;
//设置状态栏的样式
//app.statusBarStyle=UIStatusBarStyleDefault;//默认(黑色)
//设置为白色+动画效果
[app setStatusBarStyle : UIStatusBarStyleLightContent animated : YES ];
//设置状态栏是否隐藏
app. statusBarHidden = YES ;
//设置状态栏是否隐藏+动画效果
[app setStatusBarHidden : YES withAnimation : UIStatusBarAnimationFade ];
c. 补充
既然两种都可以对状态栏进行管理,那么什么时候该用什么呢?
如果状态栏的样式只设置一次,那就用 UIApplication 来进行管理;
如果状态栏是否隐藏,样式不一样那就用控制器进行管理。
UIApplication 来进行管理有额外的好处,可以提供动画效果。
4 ) openURL: 方法
UIApplication 有个功能十分强大的 openURL: 方法
- (BOOL)openURL:(NSURL*)url;
openURL: 方法的部分功能有
打电话 UIApplication *app =[UIApplicationsharedApplication]; [appopenURL:[NSURLURLWithString:@"tel://10086"]];
发短信 [app openURL:[NSURLURLWithString:@"sms://10086"]];
发邮件 [appopenURL:[NSURLURLWithString:@"mailto://12345@qq.com"]];
打开一个网页资源 [appopenURL:[NSURLURLWithString:@"http://ios.itcast.cn"]];
打开其他 app 程序 openURL 方法,可以打开其他 APP 。
URL 补充 :
URL :统一资源定位符,用来唯一的表示一个资源。
URL 格式 : 协议头: // 主机地址 / 资源路径
网络资源: http/ftp 等 表示百度上一张图片的地址 http://www.baidu.com/images/20140603/abc.png
本地资源: file:///users/apple/desktop/abc.png( 主机地址省略 )
二、 UIApplication Delegate
1. 简单说明
所有的移动操作系统都有个致命的缺点: app 很容易受到打扰。比如一个来电或者锁屏会导致 app 进入后台甚至被终止。
还有很多其它类似的情况会导致 app 受到干扰,在 app 受到干扰时,会产生一些系统事件,这时 UIApplication 会通知它的 delegate 对象,让 delegate 代理来处理这些系统事件。
作用:当被打断的时候,通知代理进入到后台。
每次新建完项目,都有个带有 “AppDelegate” 字眼的类,它就是 UIApplication 的代理 ,NJAppDelegate 默认已经遵守了 UIApplicationDelegate 协议,已经是 UIApplication 的代理。
2. 代理方法
/**
* app启动完毕后就会调用
*/
- ( BOOL )application:( UIApplication *)application didFinishLaunchingWithOptions:( NSDictionary *)launchOptions
{
NSLog ( @"%@" , self . window );
NSLog ( @"didFinishLaunchingWithOptions" );
// Override point for customizationafter application launch.
return YES ;
}
- ( void )applicationWillResignActive:( UIApplication *)application
{
}
/**
* app进入后台的时候调用
*
* 一般在这里保存应用的数据(游戏数据,比如暂停游戏)
*/
- ( void )applicationDidEnterBackground:( UIApplication *)application
{
NSLog ( @"applicationDidEnterBackground" );
}
- ( void )applicationWillEnterForeground:( UIApplication *)application
{
NSLog ( @"applicationWillEnterForeground" );
.
}
- ( void )applicationDidBecomeActive:( UIApplication *)application
{
}
/**
* 清除不需要再使用的内存
*/
- ( void )applicationDidReceiveMemoryWarning:( UIApplication *)application
{
NSLog ( @"applicationDidReceiveMemoryWarning" );
}
- ( void )applicationWillTerminate:( UIApplication *)application
{
}
@end
应用程序一般有五个状态:官方文档 app.states
三、程序启动原理
UIApplicationMain
main 函数中执行了一个 UIApplicationMain 这个函数
intUIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
argc 、 argv :直接传递给 UIApplicationMain 进行相关处理即可
principalClassName :指定应用程序类名( app 的象征),该类必须是 UIApplication( 或子类 ) 。如果为 nil, 则用 UIApplication 类作为默认值
delegateClassName :指定应用程序的代理类,该类必须遵守 UIApplicationDelegate 协议
UIApplicationMain 函数会根据 principalClassName 创建 UIApplication 对象,根据delegateClassName 创建一个 delegate 对象,并将该 delegate 对象赋值给 UIApplication 对象中的 delegate 属性
接着会建立应用程序的 Main Runloop (事件循环),进行事件的处理 ( 首先会在程序完毕后调用 delegate 对象的 application:didFinishLaunchingWithOptions: 方法 )
程序正常退出时 UIApplicationMain 函数才返回
#import <UIKit/UIKit.h>
#import "TXAppDelegate.h"
int main( int argc, char * argv[])
{
@autoreleasepool {
// return UIApplicationMain(argc, argv,nil, NSStringFromClass([TXAppDelegate class]));
@autoreleasepool {
// returnUIApplicationMain(argc, argv, nil, @"MJAppDelegate");
// returnUIApplicationMain(argc, argv, @"UIApplication",@"MJAppDelegate");
// return UIApplicationMain(argc, argv,nil, NSStringFromClass([YYAppDelegate class]));
// return UIApplicationMain(argc, argv,@"UIApplication", NSStringFromClass([YYAppDelegate class]));
/*
argc: 系统或者用户传入的参数个数
argv: 系统或者用户传入的实际参数
1.根据传入的第三个参数创建UIApplication对象
2.根据传入的第四个产生创建UIApplication对象的代理
3.设置刚刚创建出来的代理对象为UIApplication的代理
4.开启一个事件循环
*/
return UIApplicationMain (argc, argv, NSStringFromClass ([ UIApplication class ]), NSStringFromClass ([ TXAppDelegate class ]));
}
}
系统入口的代码和参数说明:
argc: 系统或者用户传入的参数
argv: 系统或用户传入的实际参数
1. 根据传入的第三个参数,创建 UIApplication 对象
2. 根据传入的第四个产生创建 UIApplication 对象的代理
3. 设置刚刚创建出来的代理对象为 UIApplication 的代理
4. 开启一个事件循环(可以理解为里面是一个死循环)这个时间循环是一个队列(先进先出)先添加进去的先处理
ios 程序启动原理
四、程序启动的完整过程
1.main 函数
2.UIApplicationMain
* 创建 UIApplication 对象
* 创建 UIApplication 的 delegate 对象
3.delegate 对象开始处理 ( 监听 ) 系统事件 ( 没有 storyboard)
* 程序启动完毕的时候 , 就会调用代理的 application:didFinishLaunchingWithOptions: 方法
* 在 application:didFinishLaunchingWithOptions: 中创建 UIWindow
* 创建和设置 UIWindow 的 rootViewController
* 显示窗口
3. 根据 Info.plist 获得最主要 storyboard 的文件名 , 加载最主要的 storyboard( 有 storyboard)
* 创建 UIWindow
* 创建和设置 UIWindow 的 rootViewController
* 显示窗口