首页 > 代码库 > 你真的了解UIApplication吗?

你真的了解UIApplication吗?

一:首先查看一下关于UIApplication的定义

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIApplication : UIResponder//获得单例对象+ (UIApplication *)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.");//委托@property(nullable, nonatomic,assign) id<UIApplicationDelegate> delegate;//暂停触摸事件- (void)beginIgnoringInteractionEvents NS_EXTENSION_UNAVAILABLE_IOS("");             // 告诉接受者继续处理 touch相关的事件- (void)endIgnoringInteractionEvents NS_EXTENSION_UNAVAILABLE_IOS(""); // 是否忽略交互事件- (BOOL)isIgnoringInteractionEvents;                 //阻止屏幕变暗进入休眠状态 ,耗电,慎重默认NO@property(nonatomic,getter=isIdleTimerDisabled)       BOOL idleTimerDisabled;// 通过特定的URL中打开资源- (BOOL)openURL:(NSURL*)url NS_EXTENSION_UNAVAILABLE_IOS(""); // 返回一个bool值, 是否从已经安装的 apps 中跳转- (BOOL)canOpenURL:(NSURL *)url NS_AVAILABLE_IOS(3_0); // 发送事件给app内适用的响应者- (void)sendEvent:(UIEvent *)event; // app的主 window 只读@property(nullable, nonatomic,readonly) UIWindow *keyWindow;// 隐藏的和看得见的所有 window@property(nonatomic,readonly) NSArray<__kindof UIWindow *>  *windows; // 发送一个含选择器的动作消息到指定的目标- (BOOL)sendAction:(SEL)action to:(nullable id)target from:(nullable id)sender forEvent:(nullable UIEvent *)event;// 是否显示网络正在活动,默认是NO@property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible; //状态栏样式@property(readonly, nonatomic) UIStatusBarStyle statusBarStyle; // default is UIStatusBarStyleDefault//状态栏隐藏@property(readonly, nonatomic,getter=isStatusBarHidden) BOOL statusBarHidden;//屏幕旋转方向@property(readonly, nonatomic) UIInterfaceOrientation statusBarOrientation;// 在指定的窗口中, 返回默认的视图控制器方向接口- (UIInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window NS_AVAILABLE_IOS(6_0);// 状态栏动画持续时间@property(nonatomic,readonly) NSTimeInterval statusBarOrientationAnimationDuration; // 获取状态栏的 rect@property(nonatomic,readonly) CGRect statusBarFrame; // 未读消息数字,0表示隐藏@property(nonatomic) NSInteger applicationIconBadgeNumber;  // 是否接受摇晃的时候, 展现 撤销和恢复 视图@property(nonatomic) BOOL applicationSupportsShakeToEdit NS_AVAILABLE_IOS(3_0);// app当前的运行的状态@property(nonatomic,readonly) UIApplicationState applicationState NS_AVAILABLE_IOS(4_0);// app 在后台运行的时间@property(nonatomic,readonly) NSTimeInterval backgroundTimeRemaining NS_AVAILABLE_IOS(4_0);//标记开始新的长时间运行的后台任务- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^ __nullable)(void))handler  NS_AVAILABLE_IOS(4_0) NS_REQUIRES_SUPER;// 标记新的长时间运行的任务以及指定任务的命名- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithName:(nullable NSString *)taskName expirationHandler:(void(^ __nullable)(void))handler NS_AVAILABLE_IOS(7_0) NS_REQUIRES_SUPER;// 结束指定的长时间的后台任务- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier NS_AVAILABLE_IOS(4_0) NS_REQUIRES_SUPER;// 指定最小时间间隔在后台获取操作- (void)setMinimumBackgroundFetchInterval:(NSTimeInterval)minimumBackgroundFetchInterval NS_AVAILABLE_IOS(7_0);//进入到后台,是否能够进行后台的操作@property (nonatomic, readonly) UIBackgroundRefreshStatus backgroundRefreshStatus NS_AVAILABLE_IOS(7_0);@property(nonatomic,readonly,getter=isProtectedDataAvailable) BOOL protectedDataAvailable NS_AVAILABLE_IOS(4_0);// 返回用户界面的布局方向。只读@property(nonatomic,readonly) UIUserInterfaceLayoutDirection userInterfaceLayoutDirection NS_AVAILABLE_IOS(5_0);// 字体偏好 只读@property(nonatomic,readonly) NSString *preferredContentSizeCategory NS_AVAILABLE_IOS(7_0);@end

UIApplication的核心作用是提供了iOS程序运行期间的控制和协作工作。它的基类是UIResponder;每一个程序在运行期必须有且仅有一个UIApplication(或则其子类)的一个实例;在程序开始运行的时候,UIApplicationMain函数是程序进入点,这个函数做了很多工作,其中一个重要的工作就是创建一个UIApplication的单例实例。在你的代码中你,你可以通过调用[UIApplication sharedApplication]来得到这个单例实例的指针。UIApplication的一个主要工作是处理用户事件,它会维护一个队列,把所有用户事件都放入队列,逐个处理,在处理的时候,它会发送当前事件到一个合适的处理事件的目标控件。此外,UIApplication实例还维护一个在本应用中打开的window列表(UIWindow实例),这样它就可以接触应用中的任何一个UIView对象。UIApplication实例会被赋予一个代理对象,以处理应用程序的生命周期事件(比如程序启动和关闭)、系统事件(比如来电、记事项警告)等等。

知识点1:属性的运用

   //通过sharedApplication获取该程序的UIApplication对象    UIApplication *app=[UIApplication sharedApplication];    app.applicationIconBadgeNumber=100;

知识点2:关于openURL的运用

/*NSURL统一资源定位符  格式 > 协议://路径*/// 创建UIApplication对象UIApplication  *app = [UIApplication sharedApplication];// 打电话 tel为打电话协议[app openURL:[NSURL URLWithString:@"tel://10086"]];// 发短信 sms为发短信协议[app openURL:[NSURL URLWithString:@"sms://10086"]];// 打开网址 http为上网协议[app openURL:[NSURL URLWithString:@"http://www.ithemima.com"]];// 发送邮件 mailto为发送邮件协议[app openURL:[NSURL URLWithString:@"mailto://zhangsan@itcast.cn"]];

知识点3:状态栏的管理从iOS7开始,系统提供了2种管理状态栏的方式

a: 通过UIViewController管理(每一个UIViewController都可以拥有自己不同的状态栏)

b: 通过UIApplication管理(一个应用程序的状态栏都由它统一管理)

在iOS7之后,默认情况下,状态栏都是由UIViewController管理的,若想通过UIApplication进行管理,则需要配置plist文件:View controller-based status bar appearance 设置成NO (默认值为YES)

// 示范代码:// 隐藏系统状态栏[UIApplication sharedApplication].statusBarHidden = YES;// 设置系统状态栏样式[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;// 隐藏系统状态栏带动画[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];// 设置系统状态栏样式带动画[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

二:UIApplication (UIRemoteNotifications)分类,处理远程通知

@interface UIApplication (UIRemoteNotifications)//在iOS8中,我们使用新的函数来注册通知- (void)registerForRemoteNotifications NS_AVAILABLE_IOS(8_0);//关闭推送- (void)unregisterForRemoteNotifications NS_AVAILABLE_IOS(3_0);//获取本地推送授权状态- (BOOL)isRegisteredForRemoteNotifications NS_AVAILABLE_IOS(8_0);//授权状态的枚举类型//UIUserNotificationTypeNone 无授权//UIUserNotificationTypeBadge 更新APP图标角标//UIUserNotificationTypeSound 播放声音//UIUserNotificationTypeAlert     屏幕中间弹出一个UIAlertView- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types NS_DEPRECATED_IOS(3_0, 8_0, "Please use registerForRemoteNotifications and registerUserNotificationSettings: instead");//获取通知中心 是否 允许程序通知消息的值。- (UIRemoteNotificationType)enabledRemoteNotificationTypes NS_DEPRECATED_IOS(3_0, 8_0, "Please use -[UIApplication isRegisteredForRemoteNotifications], or -[UIApplication currentUserNotificationSettings] to retrieve user-enabled remote notification and user notification settings");@end

知识点1:授权的方法实例

UIUserNotificationType type = UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound;UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:type categories:nil];[[UIApplication sharedApplication] registerUserNotificationSettings:setting];

知识点2:远程推送通知实现的条件

所有的苹果设备,在联网状态下,都会和苹果服务器APNs建立一个长连接;远程推送通知就是借助苹果设备与APNs服务器之间的长连接,借助APNs服务器讲消息发送给客户端。远程推送通知实现的条件,必须有真机,只有真机具备UDID,才能生成deviceToken设备令牌(deviceToken的生成算法只有Apple掌握,为了确保算法发生变化后仍然能够正常接收服务器端发送的通知,每次应用程序启动都重新获得deviceToken);需要开发推送Cer证书;

知识点3:远程推送通知步骤:

1:iOS8以后,使用远程通知,需要请求用户授权2:注册远程通知成功后会调用以下方法,获取deviceToken设备令牌:-(void)application:(UIApplication *)application        didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;3:把deviceToken设备令牌发送给服务器,时刻保持deviceToken是最新的4:监听远程推送通知:-(void)application:(UIApplication *)application        didReceiveRemoteNotification:(NSDictionary *)userInfo;

知识点4:判断是否打开推送 IOS7跟IOS8也是有区别

if ([[UIDevice currentDevice].systemVersion floatValue]>=8.0f) {UIUserNotificationSettings *setting = [[UIApplication sharedApplication] currentUserNotificationSettings];if (UIUserNotificationTypeNone == setting.types) {NSLog(@"推送关闭 8.0");}else{NSLog(@"推送打开 8.0");}}else{UIRemoteNotificationType type = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];if(UIRemoteNotificationTypeNone == type){NSLog(@"推送关闭");}else{NSLog(@"推送打开");}}

知识点5:IOS7跟IOS8关于注册通知是有差异

@interface AppDelegate ()@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    // Override point for customization after application launch.    //首次打开应用,跳转登录界面    //登录成功,跳转主界面    [self LoadMainView];    //注册远程通知    if ([[UIDevice currentDevice].systemVersion floatValue] < 8.0)    {        UIRemoteNotificationType type = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound;        [application registerForRemoteNotificationTypes:type];    }    else    {        UIUserNotificationType type = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;        UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:type categories:nil];        [application registerUserNotificationSettings:setting];    }    return YES;}#pragma mark 注册远程通知代理方法,返回deviceToken#ifdef __IPHONE_8_0- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{    //iOS8之后注册远程通知需要实现代理方法:    [application registerForRemoteNotifications];}- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler{    //handle the actions    if ([identifier isEqualToString:@"declineAction"]){    }    else if ([identifier isEqualToString:@"answerAction"]){    }}#endif- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{    NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken]                           stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];    NSLog(@"nsdata:%@\n 字符串token: %@",deviceToken, newToken);// 获取device token    //将token发送给服务器}- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{    NSLog(@"RegistFail %@",error);}- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{     //接收通知内容}

三:UIApplication (UILocalNotifications)分类 处理本地通知

@interface UIApplication (UILocalNotifications)//立刻推送,忽略本地通知对象的fireDate设置进行本地推送通知- (void)presentLocalNotificationNow:(UILocalNotification *)notification NS_AVAILABLE_IOS(4_0);//延时推送,根据本地通知对象的fireDate设置进行本地推送通知- (void)scheduleLocalNotification:(UILocalNotification *)notification NS_AVAILABLE_IOS(4_0); //取消指定的本地推送通知- (void)cancelLocalNotification:(UILocalNotification *)notification NS_AVAILABLE_IOS(4_0);//取消全部本地推送通知- (void)cancelAllLocalNotifications NS_AVAILABLE_IOS(4_0);//获取本地推送数组@property(nullable,nonatomic,copy) NSArray<UILocalNotification *> *scheduledLocalNotifications NS_AVAILABLE_IOS(4_0);         @end

知识点1:推送通知分为

本地推送通知:

不需要联网,在APP代码中推送的通知,确定知道未来某个时间点应该提醒用户什么【开发人员在APP内部通过代码发生 = 本地推送通知】

远程推送通知:

需要联网,是由服务器推送的通知,不确定未来某个时间点应该提醒用户什么【服务器可以确定通知时间和内容 = 远程推送通知】

知识点2:本地推送通知步骤

1:在iOS8以后使用本地推送通知,需要得到用户的许可2:创建UILocalNotification本地通知对象,并设置必要属性3:开始本地推送通知:第一种方法,延时推送,根据本地通知对象的fireDate设置进行本地推送通知[[UIApplication shareApplication] scheduleLocalNotification:notification];第二种方法,立刻推送,忽略本地通知对象的fireDate设置进行本地推送通知[[UIApplication shareApplication] presentLocalNotificationNow:notification];4:监听用户点击通知:APP处于前台,此时不会弹框通知用户,但会调用对应的代理方法 :-(void)application:(UIApplication *)application didReceiveLocalNotification;APP处于后台,屏幕上方会弹出横幅,用户点击横幅后,会进入前台,调用上面的代理方法。APP已关闭,屏幕上方会弹出横幅,用户点击横幅后,会启动APP,调用以下方法:-(BOOL)application:(UIApplication *)application        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;/* 通过参数launchOptions获取本地推送通知内容 */UILocalNotification *local = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];5:调用UIApplication的对象方法,取消本地推送通知:/* 取消指定的本地推送通知 */-(void)cancelLocalNotification:(UILocalNotification *)notification;/* 取消全部本地推送通知 */-(void)cancelAllLocalNotification;

知识点3:实例代码

1. 注册通知代码以及UIAlertView显示通知方法代码

- (BOOL)application:(UIApplication *)application         didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    //因为是storyboard启动,这里就没有其他启动代码了    //iOS8.0以后,如果需要使用推送通知,需要得到用户许可    if (application.currentUserNotificationSettings.types == UIUserNotificationTypeNone) {        //注册通知,有横幅通知、应用数字通知、应用声音通知        UIUserNotificationSettings * setting =               [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert |                                                           UIUserNotificationTypeBadge |                                                           UIUserNotificationTypeSound                                                categories:nil];        [application registerUserNotificationSettings:setting];    } else {        //当APP关闭后接收到通知,在启动中获取本地推送通知对象        UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];        [self showLocalNotification:notification];    }    return YES;}/* 弹框UIAlertView显示本地通知的信息 */- (void)showLocalNotification:(UILocalNotification *)notification{    /* 显示本地通知 */    NSDictionary *userInfo = notification.userInfo;    NSString *title = @"本地通知";    NSString *msg = userInfo[@"msg"];    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title                                                     message:msg                                                    delegate:nil                                           cancelButtonTitle:@"取消"                                           otherButtonTitles:@"确定", nil];    [alert show];    //移除本地通知    [[UIApplication sharedApplication] cancelLocalNotification:notification];}

2. 创建本地通知代码

/* 创建一个本地通知 */- (UILocalNotification *)makeLocalNotification{    //创建本地推送通知对象    UILocalNotification *notification = [[UILocalNotification alloc] init];    //设置调用时间    notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:10.0];//通知触发的时间,10s以后    notification.repeatInterval = NSCalendarUnitMinute;//每隔多久重复发一次本地通知    //设置通知属性    notification.alertBody = @"最近添加了诸多有趣的特性,是否立即体验?";//通知主体    notification.applicationIconBadgeNumber = 1;//应用程序图标右上角显示的消息数    notification.alertAction = @"打开应用"; //待机界面的滑动动作提示    notification.alertLaunchImage = @"Default";//通过点击通知打开应用时的启动图片,这里使用程序启动图片    notification.soundName = UILocalNotificationDefaultSoundName;//收到通知时播放的声音,默认消息声音    //设置用户信息    notification.userInfo = @{ @"id":@1,                                @"user":@"Kenshin Cui",                                @"msg":@"我来了一发本地通知"};//绑定到通知上的其他附加信息    return notification;}

如果需要每天的中午12点准时本地推送怎么办呢?就像这么办,修改fireDate和repeatInterval属性

NSDateFormatter *formatter1 = [[NSDateFormatter alloc]init];  [formatter setDateFormat:@"yyyy-MM-dd HH-mm-sss"];  NSDate *resDate = [formatter dateFromString:@"2016-04-09 12-00-00"];notification.fireDate = resDate;//设定为明天中午12点触发通知//记得设置当前时区,没有设置的话,fireDate将不考虑时区,这样的通知会不准确notification.timeZone = [NSTimeZone defaultTimeZone];notification.repeatInterval = NSCalendarUnitDay;//每隔一天触发一次

3:监听用户点击

/* 注册本地通知完成会调用,即用户点击确定授权后调用 */- (void)application:(UIApplication *)application         didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{    //在这里我们尝试发送本地推送通知    if (notificationSettings.types != UIUserNotificationTypeNone) {        UILocalNotification *notification = [self makeLocalNotification];        //延迟调用通知        [application scheduleLocalNotification:notification];        //立刻发送通知        //[application presentLocalNotificationNow:notification];    }}/* 应用还在运行,无论前台还是后台,都会调用该方法处理通知 */- (void)application:(UIApplication *)application         didReceiveLocalNotification:(UILocalNotification *)notification{    if( notification ) {        [self showLocalNotification:notification];    }}/* 应用进入前台,去除应用边角数字显示 */- (void)applicationWillEnterForeground:(UIApplication *)application {    //去除应用边角数字    [application setApplicationIconBadgeNumber:0];}

四:UIApplication (UIUserNotificationSettings)分类 ios8远程通知注册

@class UIUserNotificationSettings;@interface UIApplication (UIUserNotificationSettings)// IOS8注册远程通知- (void)registerUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings NS_AVAILABLE_IOS(8_0);// IOS8获得当前的通知设置- (nullable UIUserNotificationSettings *)currentUserNotificationSettings NS_AVAILABLE_IOS(8_0);@end

五:UIApplication (UIRemoteControlEvents)分类 远程事件开关

@interface UIApplication (UIRemoteControlEvents)//允许传递远程控制事件- (void)beginReceivingRemoteControlEvents NS_AVAILABLE_IOS(4_0);//关闭远程控制- (void)endReceivingRemoteControlEvents NS_AVAILABLE_IOS(4_0);@end

结合远程事件的运用;接收到一个远程控制事件。比如耳机控制。允许传递远程控制事件,必须调用UIApplication的beginReceivingRemoteControlEvents方法;关闭远程控制,调用endReceivingRemoteControlEvents。

六:UIApplication (UIStateRestoration)分类 控制状态恢复

@protocol UIStateRestoring;@interface UIApplication (UIStateRestoration)// 异步恢复状态- (void)extendStateRestoration  NS_AVAILABLE_IOS(6_0);// 结束异步恢复状态- (void)completeStateRestoration  NS_AVAILABLE_IOS(6_0);// 阻止应用程序使用最近的快找图像,在接下来的循环中- (void)ignoreSnapshotOnNextApplicationLaunch NS_AVAILABLE_IOS(7_0);// 注册自定义对象的使用状态恢复系统+ (void)registerObjectForStateRestoration:(id<UIStateRestoring>)object restorationIdentifier:(NSString *)restorationIdentifier NS_AVAILABLE_IOS(7_0);@end

七:UIApplicationDelegate协议

技术分享

 

//主要方法有://应用程序的生命周期//应用程序启动完成的时候调用- (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 {          NSLog(@"%s",__func__);}

 

你真的了解UIApplication吗?