iOS-UIApplication详解

iOS-UIApplication详解

✨建议收藏,用到时候一查就明白了 xx_cc

UIApplication简介

  1. UIApplication对象是应用程序的象征。
  2. 每一个应用程序都有自己的UIApplication对象,而且是单例。
  3. 一个iOS程序启动后创建的第一个对象就是UIApplication对象。
  4. 通过UIApplication *app = [UIApplication sharedApplication];可以获得这个单例对象。
  5. 利用UIApplication对象能进行一些应用级别的操作。

UIApplication单例实现原理

首先我们知道UIApplication对象是单例创建的,也就是说程序中UIApplication对象只创建一次,我们不能再新建UIApplicaiton对象。
那么当我们尝试新建一个UIApplicaiton对象时,
UIApplication *app = [[UIApplication alloc]init];
程序会报错,我们来看一下错误信息

'NSInternalInconsistencyException', reason: 'There can only be one UIApplication instance.'

这里我们发现系统的做法是抛出一个异常,告诉我们UIApplicaiton对象只能有一个。
这时我们基本可以理清,苹果内部如何实现UIApplication单例。

1.不能外界调用alloc,一调用就崩掉,抛出异常,(第一次调用alloc就不崩溃,其他都崩溃)
2.提供一个方法给外界获取单例(shareApplication)
3.程序启动的时候内部创建一次单例

下面我们来模仿一下系统单例的实现
创建Person类
Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject
//注:一般我们写单例的时候,也用shared开头,这是命名规范
+(instancetype)sharePerson;

@end

Person.m

#import "Person.h"

@implementation Person
//静态变量
static Person *_person = nil;
//类加载:每次程序一启动就会把所有类加载进内存
+(void)load
{
    _person = [[Person alloc]init];
}

+(instancetype)sharePerson
{
    return _person;
}

+(instancetype)alloc
{
    if (_person) {
        // _person有值标示已经分配好了,就不允许外界在分配内存
        // 抛异常,告诉外界不允许分配
     
        // 创建异常类
        // name:异常的名称
        // reson:异常的原因
        // userInfo:异常的信息
        NSException *excp = [NSException exceptionWithName:@"NSInternalInconsistencyException" reason:@"There can only be one Person instance." userInfo:nil];
        
        // 抛异常
        [excp raise]; 
    }
    return [super alloc];
}
@end

此时单例Person类就实现了,当我们alloc Person实例化对象的时候就会抛出异常。

一个iOS程序启动后创建的第一个对象就是UIApplication对象

那么UIApplication对象是什么时候被创建的呢?这时我们找到程序的入口main.m

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

我们发现程序一开始返回了UIApplicationMain方法,并且还有4个参数
我们来看一下这些参数的介绍
argc

The count of arguments in argv; this usually is the corresponding parameter to main.

argv

A variable list of arguments; this usually is the corresponding parameter to main.

principalClassName

The name of the UIApplication class or subclass. If you specify nil, UIApplication is assumed.

delegateClassName

The name of the class from which the application delegate is instantiated. If principalClassName designates a subclass of UIApplication, you may designate the subclass as the delegate; the subclass instance receives the application-delegate messages. Specify nil if you load the delegate object from your application’s main nib file.

argc:系统或者用户传入的参数
argv:系统或用户传入的实际参数

重点放在第三、四个参数

第三个参数 nil:代表UIApplication类名或者子类名称,nil 相当于 @"UIApplicaiton";
第四个参数 :代表UIApplicaiton的代理名称 NSStringFromClass([AppDelegate class] 相当于 @"AppDelegate";

此时我们可以根据UIApplicationMain函数了解程序启动的过程

  1. 根据传递的类名创建UIApplication对象,这是第一个对象
  1. 创建UIApplication代理对象,并给UIApplicaiton对象设置代理
  2. 开启主运行循环 main events loop处理事件,保持程序一直运行
  3. 加载info.plist,判断是否指定mian(xib 或者 storyboard)如果指定就去加载

利用UIApplication对象能进行一些应用级别的操作。

  • 设置应用程序图标右上角的红色提醒数字
    @property(nonatomic) NSInteger applicationIconBadgeNumber;
    代码实现和效果:
UIApplication *app = [UIApplication sharedApplication];
app.applicationIconBadgeNumber = 10;
// 创建通知对象
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
// 注册用户通知
[app registerUserNotificationSettings:setting];

注:苹果为了增强用户体验,在iOS8以后我们需要创建通知才能实现图标右上角提醒,iOS8之前直接设置applicationIconBadgeNumber的值即可。

提醒效果图
  • 设置联网指示器的可见性
    @property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
    代码实现和效果:
app.networkActivityIndicatorVisible= YES;
联网指示器显示效果图
  • 管理状态栏
    从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的设置,添加选中行,并设置为NO即可,这篇文章中有详细介绍iOS中用application 来管理电池栏状态

Info.plist的设置

代码:

//通过sharedApplication获取该程序的UIApplication对象
UIApplication *app=[UIApplication sharedApplication];
//设置状态栏的样式
//app.statusBarStyle=UIStatusBarStyleDefault;//默认(黑色)
//设置为白色+动画效果
[app setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
//设置状态栏是否隐藏
app.statusBarHidden=YES;
//设置状态栏是否隐藏+动画效果
[app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];

c.总结

如果状态栏的样式只设置一次,那就用UIApplication来进行管理,并且UIApplication可以提供动画效果;
如果状态栏是否隐藏,样式不一那就用每个控制器对自己的状态栏进行管理。

  • openURL:方法
    UIApplication有个功能十分强大的openURL:方法
    - (BOOL)openURL:(NSURL*)url;
    openURL:方法的部分功能有
UIApplication *app = [UIApplicationsharedApplication];
打电话  [app openURL:[NSURLURLWithString:@"tel://110"]];
发短信  [app openURL:[NSURLURLWithString:@"sms://10086"]];
发邮件  [app openURL:[NSURLURLWithString:@"mailto://xxcc@fox.com"]];
打开一个网页资源 [app openURL:[NSURL URLWithString:@"http://www.baidu.com"]];
打开其他app程序   openURL方法,可以打开其他APP。

系统内部根据不同的头标示来做出不同的相应。

  • 判断程序运行状态
    //判断程序运行状态
    /*
     UIApplicationStateActive, 
     UIApplicationStateInactive, 
     UIApplicationStateBackground
     */
 UIApplication *app = [UIApplication sharedApplication];
 if(app.applicationState ==UIApplicationStateInactive){
        NSLog(@"程序在运行状态");
    }
  • 阻止屏幕变暗进入休眠状态
    //阻止屏幕变暗,慎重使用本功能,因为非常耗电。
   UIApplication *app = [UIApplication sharedApplication];
   app.idleTimerDisabled =YES;

UIApplication Delegate

当app收到干扰,例如程序运行中来电等,就会产生一些系统事件,这时UIApplicaiton会通知它的代理delegate对象,让delegate代理来处理这些系统事件。
delegate可以处理的时间包括

1.应用程序的生命周期事件(如程序启动和关闭)
2.系统事件(如来电)
3.内存警告(用处较多)

每当我们创建项目时,程序中的AppDelegate文件就是UIAppliacation的代理,我们可以发现它已经遵守了UIApplicationDelegate。

@interface AppDelegate : UIResponder <UIApplicationDelegate>
下面我们来看一下AppDelegate的方法

// AppDelegate:监听应用程序的生命周期
// 以下方法就是应用程序的生命周期方法

// 应用程序启动完成的时候就会调用AppDelegate的方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"%s",__func__);
    return YES;
}
// 当应用程序失去焦点的时候调用
- (void)applicationWillResignActive:(UIApplication *)application {
     NSLog(@"%s",__func__);
}
// 当应用程序进入后台的时候调用
- (void)applicationDidEnterBackground:(UIApplication *)application {
     NSLog(@"%s",__func__);
    // 保存一些信息
}
// 当应用程序进入前台的时候调用
- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"%s",__func__);
}
// 当应用程序完全获取焦点的时候调用
// 只有当应用程序完全获取焦点的时候,才能够与用户交互
- (void)applicationDidBecomeActive:(UIApplication *)application {
     NSLog(@"%s",__func__);
}
// 当应用程序关闭的时候
- (void)applicationWillTerminate:(UIApplication *)application {
    
}
//收到内存警告时调用
-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application{

}

本文借鉴了很多前辈的文章,如果有不对的地方请指正,欢迎大家一起交流学习

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容