美文网首页程序员iOS Developer
[程序员日记]又见UIApplication

[程序员日记]又见UIApplication

作者: KeyLiu7 | 来源:发表于2017-03-22 13:57 被阅读341次

在开发过程中,我们很少真正研究过这个类,很多半路出家的程序员对于view的生命周期有所了解,但对UIApplication未深入研究。在开发过程中,相信我们都或多或少的使用了其中的很多功能,下面就来探讨和总结一下其中的内容,又见iOS,就让我们从main开始,重新进入iOS的新世界。

应用程序生命周期

简述UIApplication##

UIApplication的核心作用是提供了iOS程序运行期间的控制和协作工作。每一个程序在运行期必须有且仅有一个UIApplication(或则其子类)的一个实例。在程序开始运行的时候,UIApplicationMain函数是程序进入点,这个函数做了很多工作,其中一个重要的工作就是创建一个UIApplication单例实例。在你的代码中你,你可以通过调用[UIApplication sharedApplication]来得到这个单例实例的指针。

UIApplication的一个主要工作是处理用户事件,它会起一个队列,把所有用户事件都放入队列,逐个处理,在处理的时候,它会发送当前事件到一个合适的处理事件的目标控件。此外,UIApplication实例还维护一个在本应用中打开的window列表(UIWindow实例),这样它就可以接触应用中的任何一个UIView对象。UIApplication实例会被赋予一个代理对象,以处理应用程序的生命周期事件(比如程序启动和关闭)、系统事件(比如来电、记事项警告)等等。

新建一个任意类型的iOS应用工程,我们可以看到工程中生成一个类:
AppDelegate :UIResponder <UIApplicationDelegate>
这里这个类的基类是UIResponder(注:iOS 4.2以前生成的工程是不同的,以前是继承自NSObject)。不论如何,本类实现了一个名叫UIApplicationDelegate的接口,这个表明这个类就是这个工程中UIApplication实例的代理类。

main函数中,

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

这里传入了代理类到UIApplicationMain函数中,UIApplicationMain函数在生成唯一个UIApplication的时候就可以把代理类的实例指针告诉这个单例对象了。

[注]参数说明
argc:系统或者用户传入的参数
argv:系统或用户传入的实际参数
1.根据传入的第三个参数,创建UIApplication对象
2.根据传入的第四个产生创建UIApplication对象的代理
3.设置刚刚创建出来的代理对象为UIApplication的代理
4.开启一个事件循环(可以理解为里面是一个死循环)这个时间循环是一个队列(先进先出)先添加进去的先处理

UIApplication生命周期##

1、
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

说明:当应用程序正常启动时(不包括已在后台转到前台的情况),调用此回调。launchOptions是启动参数,假如用户通过点击push通知启动的应用,(这是非正常启动的情况,包括本地通知和远程通知),这个参数里会存储一些push通知的信息。

2、
- (void)applicationWillResignActive:(UIApplication *)application

说明:当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话了

3、
- (void)applicationDidBecomeActive:(UIApplication *)application

说明:当应用程序入活动状态执行,这个刚好跟上面那个方法相反

4、
- (void)applicationDidEnterBackground:(UIApplication *)application

说明:当程序被推送到后台的时候调用。所以要设置后台继续运行,则在这个函数里面设置即可

5、
- (void)applicationWillEnterForeground:(UIApplication *)application

说明:当程序从后台将要重新回到前台时候调用,这个刚好跟4相反。

6、
- (void)applicationWillTerminate:(UIApplication *)application

说明:当程序将要退出是被调用,通常是用来保存数据和一些退出前的清理工作。这个需要要设置UIApplicationExitsOnSuspend的键值。

7、
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application

说明:iPhone设备只有有限的内存,如果为应用程序分配了太多内存操作系统会终止应用程序的运行,在终止前会执行这个方法,通常可以在这里进行内存清理工作防止程序被终止

8、
- (void)applicationSignificantTimeChange:(UIApplication*)application

说明:当系统时间发生改变时执行

9、
- (void)applicationDidFinishLaunching:(UIApplication*)application

说明:当程序载入后执行

10、
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
说明:当客户端注册远程通知时,会回调的方法。
如果成功,则回调这个方法,客户端把deviceToken取出来发给服务端,push消息的时候要用。
如果失败了,则回调下面的方法,可以从error参数中看一下失败原因。

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error

11、
- (void)application:(UIApplication)application willChangeStatusBarFrame:(CGRect)newStatusBarFrame

说明:当StatusBar框将要变化时执行

- (void)application:(UIApplication*)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientationduration:(NSTimeInterval)duration

说明:当StatusBar框方向将要变化时执行

- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation

说明:当StatusBar框方向变化完成后执行

- (void)application:(UIApplication*)application didChangeSetStatusBarFrame:(CGRect)oldStatusBarFrame

说明:当StatusBar框变化完成后执行

12、
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url

说明:当通过url执行

13、

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo

说明:当应用在前台运行中,收到远程通知时(不会弹出系统通知界面),会回调这个方法。
当应用在后台状态时,点击push消息启动应用,也会回调这个方法。
当应用完全没有启动时,点击push消息启动应用,就不会回调这个方法。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler

与上一方法相同,区别是在后台时亦可执行方法,但要开启相关权限。如图。


开启权限
-  (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification

说明:当应用收到本地通知时会调这个方法,同上面一个方法类似。
如果在前台运行状态直接调用
如果在后台状态,点击通知启动时,也会回调这个方法
当应用完全没有启动时,点击push消息启动应用,就不会回调这个方法。

[补充]1.iPhone中的应用程序很容易受到打扰,比如一个来电可能导致应用程序失去焦点,如果这个时候接听了电话,那么应用程序会转到后台运行。还有很多其它类似的事件会导致iPhone应用程序失去焦点,在应用程序失去焦点前会调用委托类的applicationWillResignActive()方法,而应用程序再次获取到焦点的时候会调用applicationDidBecomeActive()方法。比如在运行应用程序的时候锁屏会调用委托类的applicationWillResignActive()方法,而当屏幕被解锁的时候,又会调用applicationDidBecomeActive()方法。

2.另外一个非常重要的方法就是applicationDidReceiveMemoryWarning(),因为iPhone设备只有有限的内存,如果为应用程序分配了太多内存操作系统会终止应用程序的运行,但在终止之前操作系统会通过先调用委托类的applicationDidReceiveMemoryWarning()方法警告应用程序,在UIApplication接收到这个事件后它会传递给委托类的applicationDidReceiveMemoryWarning()方法,委托类在这个方法内可以进行释放内存的操作以防止操作系统强制终止应用程序的运行。

UIApplication部分常用功能##

1.设置icon上的数字图标,缺省为0

[UIApplication sharedApplication].applicationIconBadgeNumber = 1;

2.设置摇动手势的时候,是否支持redo,undo操作,缺省YES

[UIApplication sharedApplication].applicationSupportsShakeToEdit =YES;

3.判断程序运行状态

typedef NS_ENUM(NSInteger, UIApplicationState) {
    UIApplicationStateActive, 
    UIApplicationStateInactive,
    UIApplicationStateBackground
} NS_ENUM_AVAILABLE_IOS(4_0);

if([UIApplicationsharedApplication].applicationState ==UIApplicationStateInactive){
    NSLog(@"程序在运行状态");
 }

4.阻止屏幕变暗进入休眠状态,缺省为no

 [UIApplication sharedApplication].idleTimerDisabled =YES;

[注意⚠️]除视频播放等需要常亮等功能外,慎重使用本功能,因为非常耗电

5.显示联网状态动画

[UIApplication sharedApplication].networkActivityIndicatorVisible =YES;

6.设置状态栏的样式

typedef NS_ENUM(NSInteger, UIStatusBarStyle) {
    UIStatusBarStyleDefault   = 0, // 默认样式,黑字,适用于浅色背景(iOS6及以下系统状态栏为黑底白字)
    UIStatusBarStyleLightContent     NS_ENUM_AVAILABLE_IOS(7_0) = 1, // 白字,适用于深色背景
    UIStatusBarStyleBlackTranslucent NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 1,// 白字(iOS6及以下系统在启动界面为灰底白字,iOS7及以上系统与UIStatusBarStyleBlackOpaque效果一样)
    UIStatusBarStyleBlackOpaque      NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 2,// 白字,适用于深色背景(iOS6及以下系统状态栏为黑底白字)
} __TVOS_PROHIBITED;

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

隐藏状态栏

[UIApplication sharedApplication].statusBarHidden = YES;

7.调用系统功能
openURL是UIApplication中一个非常强大的方法,使用其可以调用系统相关功能。其方法有

 - (BOOL)openURL:(NSURL*)url ;
 - (BOOL)canOpenURL:(NSURL *)url ;

[注]在iOS10后新增- (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options completionHandler:(void (^ __nullable)(BOOL success))completion方法

常用方法有:

(1)发送电子邮件

 NSString *recipients =@"mailto:first@example.com?cc=second@example.com,third@example.com&subject=Hello from California!";
 NSString *body =@"&body=It is raining in sunny California!";
 NSString *email = [NSString  stringWithFormat:@"%@%@", recipients, body];
 email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:email]];

(2)打电话

[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"tel://1234567890"]];

(3)发送短信

[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"sms://466453"]];

(4)打开一个网址

[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"http://itunesconnect.apple.com"]];

[补充] 打开网址的操作通常用于跳转app store,iOS给好评时一般会直接打开app store应用详情界面,其实也可以直接跳转到评论页面,更有利于引导用户打分和评论。(将下面id改成自己的app id即可)

[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=id1128294199&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8"]];

直接跳转到详情

https://itunes.apple.com/cn/app/jia-zhang-mu-ke/id1128294199?mt=8

8.推送相关
注册推送

 [[UIApplication sharedApplication]registerUserNotificationSettings:setting];

移除推送

 [[UIApplication sharedApplication] cancelAllLocalNotifications];

添加推送

 [[UIApplication sharedApplication]  scheduleLocalNotification:notification];

更多内容会陆续补充,欢迎参考指正。

文章参考:
1.UIApplication深入研究-博客园
2.iOS开发UI篇—程序启动原理-博客园

文章优先发表于:http://keyliu.com
转载请注明出处。

相关文章

网友评论

    本文标题:[程序员日记]又见UIApplication

    本文链接:https://www.haomeiwen.com/subject/aoefnttx.html