iOS UIApplication详解(待更新)

UIApplication对象是应用程序的象征

  • 每一个应用都有自己的UIApplication对象,而且是单例的
  • 通过[UIApplication sharedApplication]可以获得这个单例对象,命名规范一般单例都是使用shared拿到
  • 一个iOS程序创建的第一个对象就是UIApplication对象
  • 利用UIApplication对象,能进行一些应用级别操作

什么是单例?

整个应用程序中只有一份,即只有一份内存,并不会分配多余的内存
新建项目,在ViewDidLoad中创建,会崩溃,原因为红色所圈部分


单例演示

苹果单例实现:

1.内部创建单例对象,程序启动的时创建该单例
2.提供一个方法,方便给外界获取单例对象
3.外界不能调用alloc方法,一调用就会崩溃,即抛异常

模仿UIApplication单例对象的实现,来更好的认识UIApplication

1.创建一个CrabMan,通过重写类方法load来模仿(类名随意)项目一启动就创建对象。load方法会在程序一启动时自动调用,将程序中所有的类加载出来,下图为验证效果图

+load方法讲解

2.创建并保存对象
创建完成后,使用静态全局变量来保存,并声明share方法供外部调用
疑问:为什么不用属性来保存?
解答:因为属性是属于对象的,在load方法对象还未创建完成,不能用对象的属性来保存该对象本身。

疑问:为什么只在.m文件中实现load方法?
解答:我们demo的目的是演示UIApplication的单例,对象的创建在内部进行,获取单例对象的方法提供给外部使用,该解答也回答了为什么shareCranMan方法需要在.h文件中声明。

对象的创建以及保存

3.重写系统alloc方法并抛异常
疑问:为什么return返回的是[super alloc]
解答:调用系统默认的方法,因为我们不知道分配内存的实现,又不想要覆盖原来方法的实现,所以就需要调用super alloc方法并将其返回

重新alloc方法

4.演示结果,外界调用alloc崩溃


结果演示

UIApplication的常用属性

  • 设置应用程序图标右上角的红色提醒数字
    @property(nonatomic) NSInteger applicationIconBadgeNumber;
badge
  • 设置联网指示器的可见性
    @property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL NetworkActivityIndicatorVisible;
    联网指示器
  • iOS 7 的状态栏
  • 打电话,发短信(需要真机)打开网页
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    UIApplication *application = [UIApplication sharedApplication];
    //1.获取应用程序图标的提醒数字
    /**
     设置后无效,查看属性下的英文注释:
     set to 0 to hide. default is 0. In iOS 8.0 and later, your application must register for user notifications using -[UIApplication registerUserNotificationSettings:] before
     */
    application.applicationIconBadgeNumber = 10;
    //创建通知对象
       UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
    //注册用户通知
    [application registerUserNotificationSettings:setting];
    
    //2.设置联网提示
    application.networkActivityIndicatorVisible = YES;
    
    
    //3.设置状态栏
    
    //application.statusBarHidden = YES;
    /**
     设置无效,查看官方注释
      Setting statusBarHidden does nothing if your application is using the default UIViewController-based status bar system.
     iOS7之后默认交给控制器管理状态栏
     */
   // - (BOOL)prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to NO
    // Override to return the type of animation that should be used for status bar changes for this view controller. This currently only affects changes to prefersStatusBarHidden.
    //配置info:添加key:View controller-based status bar appearance,并设置为NO,将状态栏的设置交给application来管理
    
    //方法已经过期
    [application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
    
    
    //4.打电话 发信息 打开网页
    
    //打开网页:URL:资源的唯一标示;协议头+资源路径
    //原理:根据协议头判断用什么软件打开
    [application openURL:[NSURL URLWithString:@"http://www.baidu.com"]];    
}

UIApplication和delegate

  • 所有的移动操作系统都有个致命的缺点:app很容易受到打扰。比如一个来电或者是锁屏会导致app进入后台甚至终止。
  • 还有很多其他类似的情况都会导致app受到干扰,app受到干扰时,会产生一系列系统事件,这时UIApplication会通知他的delegate对象,让delegate来处理系统事件

delegate可处理的事件包括:

  • 应用程序的生命周期事件(如程序的启动和关闭)
  • 系统事件(如来电)
  • 内存警告
UIApplication和delegate

delegate方法讲解:

//应用程序启动完成后就会调用AppDelegate方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    return YES;
}
//当应用程序失去焦点的时候调用,只有当应用程序完全获取焦点的时候才能够与用户交互,所谓的获取焦点我的理解为app启动布满屏幕。
- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
//当应用程序进入后台时候调用
- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
//当应用程序即将进入前台的时候调用
- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
//当应用程序获得焦点的时候调用
- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
//当应用程序关闭的时候调用
- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

各方法的调用时机的演示以及讲解
1.程序一启动未做任何操作
程序加载完毕,并获得焦点


程序启动

2.点击home键进入手机主界面
application先失去焦点然后 进入后台


程序进入后台

3.点击应用重新进入
application进入前台然后获得焦点


程序进入前台

4.双击home键关闭程序
程序关闭
关闭程序

由控制台打印结果可知按照上面的操作,先后顺序为:
程序加载完毕-->程序获得焦点-->程序失去焦点-->程序进入后台-->程序进入前台-->程序获得焦点-->程序关闭

程序的启动流程

讲解

演示main以及控制台打印结果

查看官方文档,了解参数的介绍
第三个参数:UIApplication类名或者子类的名称,如果传nil的话默认为@“UIApplication”
第四个参数:UIApplication的代理的类型名称,苹果使用NSStringFromClass([AppDelegate class])方法,获得对应类名,使用该方法除了可以避免输入错误的同时还具有提示功能。


官方文档

UIApplication底层实现原理:

1.根据principalClassName(第三个参数)传递的类名创建一个UIApplication对象
2.创建UIApplication代理对象,给UIApplication对象设置代理
3.开启主运行事件循环,处理事件,保持程序一直运行(后期runloop讲解)
4.加载Info.plist,判断application的Info.pist文件是否指定main,如果指定main就会记载nib文件

iOS程序的启动过程流程图

流程图

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 22,334评论 41 457
  • 1.属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作...
    曾令伟阅读 483评论 0 8
  • *7月8日上午 N:Block :跟一个函数块差不多,会对里面所有的内容的引用计数+1,想要解决就用__block...
    炙冰阅读 1,131评论 1 8
  • 1,NSObject中description属性的意义,它可以重写吗?答案:每当 NSLog(@"")函数中出现 ...
    eightzg阅读 2,653评论 2 18
  • 一直都知道有一种家叫娘家,但未曾感受过。如今,我也有了娘家,有了婆家,但心里并没感觉到更加的安稳和平静,更多的是不...
    一瞬间的回转阅读 27评论 0 0