本文作为开篇必然要交代一些事情,第一是语言的选择上是swift,第二是iOS版本兼容上8.0+。swift3.0已经基本稳定,swift是未来趋势也是个人趋势。至于iOS版本,苹果官方显示iOS9以上的用户已经占到98%了,况且鹅厂的QQ和微信已经放弃8.0-,我想没有哪个公司有理由坚持了(如果有请告诉我?)。 所以,系列文章的开发环境都是swift3.1+Xcode8.3.3,适配系统iOS8.0+。 对于专业名词和其他翻译不好的名词会使用英文或者附带英文。
简介
UIApplication类为在iOS系统中运行的应用提供了一个集中的控制和协调点,也就是说UIApplication对象是iOS系统与应用程序中其他对象交互的桥梁。每个应用程序都有一个UIApplication
的实例。当应用程序启动时,系统调用UIApplication(:::)函数创建一个单例对象。在其他地方可以通过shared方法访问该对象。
应用程序对象的主要任务是处理传入的用户事件的初始路由。它通过控制器对象(UIControl类的实例)向适当的目标对象发送操作消息。应用程序对象维护一个开放的窗口列表,通过这可以检索任何UIView对象。
UIApplication 类定义了一个符合UIApplicationDelegate
协议的委托,并且必须实现一些协议方法。应用程序对象会通知重要的运行时事件的委托,例如应用启动、低内存警告和应用程序终止,使app本身有机会做出合适的响应。
通过openURL(_:)方法应用程序可以协调处理一些如email或image等文件资源。例如一个应用使用电子邮件地址调用该方法会导致邮件应用启动并且显示一些信息。 这些api允许你管理特定的设备行为,可以使用UIApplication对象实现以下行为:
- 临时拦截传入的触摸事件:beginIgnoringInteractionEvents()
- 注册推送通知
- 触发undo-redo UI
- 确定是否安装了一个已注册的应用程序来处理一个URL方案:canOpenURL(_:)
- 延长应用程序的执行,这样它就可以在后台完成任务:beginBackgroundTask(expirationHandler:) , beginBackgroundTask(withName:expirationHandler:)
- 设定和取消本地通知: scheduleLocalNotification(:) , cancelLocalNotification(:)
- 执行应用级的状态恢复:
大多数应用都不需要子类化UIApplication,只需要使用应用程序代理来管理应用程序和系统的交互。如果需要在系统处理之前就处理事件,这是很罕见的,你可以实现自定义的事件调度机制。继承自UIApplication,然后重写sendEvent(_:)
或者sendAction(_:to:from:for:)
方法。处理完记得调用[super sendEvent:event]恢复该事件的调度循环。
获取应用程序单例
定义
class var shared: UIApplication { get }
复制代码
实质上,应用程序对象是在函数 UIApplicationMain(_:_:_:_:)
中创建的。这个函数中做了很多事情,实例化应用程序类,设置应用程序委托,还设置了主事件循环the main event loop
,包含应用程序的运行循环application’s run loop
,并开始处理事件。如果info.plist中设置了需要加载的主nib文件,并且nib文件可用则会加载nib。
应用程序代理和生命周期
- 应用程序代理
多数情况下应用程序代理是唯一获取应用程序状态变化等重要通知的唯一方式。 AppDelegate是单例根对象。尽管UIApplication完成了大部分的底层工作,但应该实现AppDelegate的多数或者全部的代理方法来决定应用的总体行为。 应用程序代理扮演了一个非常重要的角色:
- 包含了应用程序的启动代码
- 对应用程序状态的变化做出响应
- 响应外来通知,如低内存警告、下载完成等通知
- 决定状态的保存和恢复是否 应该发生,并在需要的情况下协助保存和恢复过程。 您可以使用它来存储应用程序的中央数据对象或任何没有拥有视图控制器的内容。
应用委托在启动时执行的一些额外任务包括以下内容:
- 查看启动选项字典,以确定你的应用程序启动的原因
application(_:willFinishLaunchingWithOptions:)
方法和application(_:didFinishLaunchingWithOptions:)
方法均提供了一个字典指示app启动的原因 - 确定状态恢复是否应该进行,如果应用程序保存了视图控制器的状态,那么只有在应用程序代理方法
application(_:shouldRestoreApplicationState:)
返回为true
时才会恢复之前的状态。 - 注册远程通知
- 处理URL
- 提供根窗口对象
应用程序启动时传递过来的字典,让我们在程序启动时调整应用程序界面展示的内容。比如接收到远程通知启动时需要展示通知内容。
- 管理应用程序状态变化(生命周期) 应用委托的主要工作之一是响应系统报告的状态转换。对于发生的每一个状态更改,系统调用应用委代理的对应方法。每个状态都有不同的规则来管理应用程序的表现,应用代理必须相应地调整应用程序的行为。
- 没有运行(Not running) 应用程序没有打开或者被终止
- 不活跃(Inactive) 应用程序在前台运行但是不接收事件。一般情况下这个状态都是短站停留,很快进入后台或者变为活跃状态。
- 活跃(Active) 应用程序在前台运行,并且接收事件,对用户行为做出响应。
- 后台(Background) 应用程序仍在执行代码但是在屏幕上已不可见。当用户退出应用程序时,系统会在应用挂起前将应用程序短暂地转移到后台状态。其他情况下系统也会将应用程序直接登录到后台状态,或者将应用程序从挂起状态唤醒,并给他处理特定任务的时间。比如后台下载,特定的定位,远程通知等。 在后台处理的任务应该尽量少,尽快将控制权交还给系统
- 暂停/挂起(Suspended) 应用还在内存中但是不执行任何代码。系统会挂起在后台
没有待完成任务
的应用。系统可能会为其他应用腾出空间而随时清理处于挂起状态的应用。
应用程序状态变化时调用的代理方法
-
登入时(Launch time)
- application(_:willFinishLaunchingWithOptions:) 启动过程开始,状态恢复还未发生
返回值:当应用无法处理URL资源或者继续用户活动时,返回值为false。如果应用程序是因为远程通知而启动的那么返回值会被忽略optional func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool 复制代码
- application(_:willFinishLaunchingWithOptions:) 启动过程开始,状态恢复还未发生