Swift - RxSwift的使用详解60(DelegateProxy样例3:应用生命周期的状态变化)
作者:hangge | 2018-05-14 08:10
我们知道 UIApplicationDelegate 协议中定义了关于程序启动各个过程的回调,比如:
- applicationWillResignActive 方法:在应用从活动状态进入非活动状态的时候会被调用(比如电话来了)。
- applicationWillTerminate 方法:在应用终止的时候会被调用。
过去我们通常都是在 AppDelegate.swift 里的相关回调方法中编写相应的业务逻辑。但一旦功能复杂些,这里就会变得十分混乱难以维护。而且有时想在其它模块中使用这些回调也不容易。
本文演示如何通过对 UIApplication 进行 Rx 扩展,利用 RxSwift 的 DelegateProxy 实现 UIApplicationDelegate 相关回调方法的封装。从而让 UIApplicationDelegate 回调可以在任何模块中都可随时调用。
四、监测应用生命周期的状态变化
1,准备工作
(1)RxUIApplicationDelegateProxy.swift
首先我们继承 DelegateProxy 创建一个关于应用生命周期变化的代理委托,同时它还要遵守 DelegateProxyType、UIApplicationDelegate 协议。
import RxSwift import RxCocoa import UIKit //UIApplicationDelegate 代理委托 public class RxUIApplicationDelegateProxy : DelegateProxy<UIApplication, UIApplicationDelegate>, UIApplicationDelegate, DelegateProxyType { public weak private(set) var application: UIApplication? init(application: ParentObject) { self.application = application super.init(parentObject: application, delegateProxy: RxUIApplicationDelegateProxy.self) } public static func registerKnownImplementations() { self.register { RxUIApplicationDelegateProxy(application: $0) } } public static func currentDelegate(for object: UIApplication) -> UIApplicationDelegate? { return object.delegate } public static func setCurrentDelegate(_ delegate: UIApplicationDelegate?, to object: UIApplication) { object.delegate = delegate } override open func setForwardToDelegate(_ forwardToDelegate: UIApplicationDelegate?, retainDelegate: Bool) { super.setForwardToDelegate(forwardToDelegate, retainDelegate: true) } }
(2)UIApplication+Rx.swift
接着我们对 UIApplication 进行 Rx 扩展,作用是将 UIApplication 与前面创建的代理委托关联起来,将状态变化相关的 delegate 方法转为可观察序列。
注意1:我们在开头自定义了一个表示应用状态枚举(AppState),不使用系统自带的的 UIApplicationState 是因为后者没有 terminated(终止)这个状态。
注意2:下面代码中将 methodInvoked 方法替换成 sentMessage 其实也可以,它们的区别可以看我的另一篇文章:
import RxSwift import RxCocoa import UIKit //自定义应用状态枚举 public enum AppState { case active case inactive case background case terminated } //扩展 extension UIApplicationState { //将其转为我们自定义的应用状态枚举 func toAppState() -> AppState{ switch self { case .active: return .active case .inactive: return .inactive case .background: return .background } } } //UIApplication的Rx扩展 extension Reactive where Base: UIApplication { //代理委托 var delegate: DelegateProxy<UIApplication, UIApplicationDelegate> { return RxUIApplicationDelegateProxy.proxy(for: base) } //应用重新回到活动状态 var didBecomeActive: Observable<AppState> { return delegate .methodInvoked(#selector(UIApplicationDelegate.applicationDidBecomeActive(_:))) .map{ _ in return .active} } //应用从活动状态进入非活动状态 var willResignActive: Observable<AppState> { return delegate .methodInvoked(#selector(UIApplicationDelegate.applicationWillResignActive(_:))) .map{ _ in return .inactive} } //应用从后台恢复至前台(还不是活动状态) var willEnterForeground: Observable<AppState> { return delegate .methodInvoked(#selector(UIApplicationDelegate.applicationWillEnterForeground(_:))) .map{ _ in return .inactive} } //应用进入到后台 var didEnterBackground: Observable<AppState> { return delegate .methodInvoked(#selector(UIApplicationDelegate.applicationDidEnterBackground(_:))) .map{ _ in return .background} } //应用终止 var willTerminate: Observable<AppState> { return delegate .methodInvoked(#selector(UIApplicationDelegate.applicationWillTerminate(_:))) .map{ _ in return .terminated} } //应用各状态变换序列 var state: Observable<AppState> { return Observable.of( didBecomeActive, willResignActive, willEnterForeground, didEnterBackground, willTerminate ) .merge() .startWith(base.applicationState.toAppState()) //为了让开始订阅时就能获取到当前状态 } }
2,使用样例1
(1)我们可以对各个状态变化行为分别进行订阅:import UIKit import RxSwift import RxCocoa class ViewController: UIViewController { let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() //应用重新回到活动状态 UIApplication.shared.rx .didBecomeActive .subscribe(onNext: { _ in print("应用进入活动状态。") }) .disposed(by: disposeBag) //应用从活动状态进入非活动状态 UIApplication.shared.rx .willResignActive .subscribe(onNext: { _ in print("应用从活动状态进入非活动状态。") }) .disposed(by: disposeBag) //应用从后台恢复至前台(还不是活动状态) UIApplication.shared.rx .willEnterForeground .subscribe(onNext: { _ in print("应用从后台恢复至前台(还不是活动状态)。") }) .disposed(by: disposeBag) //应用进入到后台 UIApplication.shared.rx .didEnterBackground .subscribe(onNext: { _ in print("应用进入到后台。") }) .disposed(by: disposeBag) //应用终止 UIApplication.shared.rx .willTerminate .subscribe(onNext: { _ in print("应用终止。") }) .disposed(by: disposeBag) } }
(2)我们进行在如下一系列操作后,控制台里内容如下:
- 编译运行程序
- 按下 home 键程序进入后台
- 双击 home 键,选择程序并回到前台
3,使用样例2
(1)我们也可以对状态变化序列进行订阅:
import UIKit import RxSwift import RxCocoa class ViewController: UIViewController { let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() //应用重新回到活动状态 UIApplication.shared.rx .state .subscribe(onNext: { state in switch state { case .active: print("应用进入活动状态。") case .inactive: print("应用进入非活动状态。") case .background: print("应用进入到后台。") case .terminated: print("应用终止。") } }) .disposed(by: disposeBag) } }
(2)我们进行在如下一系列操作后,控制台里内容如下:
- 编译运行程序
- 按下 home 键程序进入后台
- 双击 home 键,选择程序并回到前台
全部评论(1)
大哥你是真的很猛阿…
站长回复:谢谢你的夸奖