有没有觉得你的AppDelegate杂乱无章?代码几百行上千行?集成了无数的功能,如推送、埋点、日志统计、Crash统计等等,感觉AppDelegate无所不能。

来一段一般的AppDelegate代码,来自网上一篇文章:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {var window: UIWindow?func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {Log(info: "AppDelegate.didFinishLaunchingSite started.")application.setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum)UNUserNotificationCenter.current().register(delegate: self,actions: [UNNotificationAction(identifier: "favorite", title: .localized(.favorite))])// Initialize Google Analyticsif !AppGlobal.userDefaults[.googleAnalyticsID].isEmpty {GAI.sharedInstance().tracker(withTrackingId: AppGlobal.userDefaults[.googleAnalyticsID])}// Declare data format from remote REST APIJSON.dateFormatter.dateFormat = ZamzamConstants.DateTime.JSON_FORMAT// Initialize componentsAppLogger.shared.setUp()AppData.shared.setUp()// Select home tab(window?.rootViewController as? UITabBarController)?.selectedIndex = 2setupTheme()Log(info: "App finished launching.")// Handle shortcut launchif let shortcutItem = launchOptions?[.shortcutItem] as? UIApplicationShortcutItem {performActionForShortcutItem(application, shortcutItem: shortcutItem)return false}return true}func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let webpageURL = userActivity.webpageURL else { return false }Log(info: "AppDelegate.continueUserActivity for URL: \(webpageURL.absoluteString).")return navigateByURL(webpageURL)}func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {Log(info: "AppDelegate.performFetch started.")scheduleUserNotifications(completionHandler: completionHandler)}func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {window?.rootViewController?.dismiss(animated: false, completion: nil)guard let tabController = window?.rootViewController as? UITabBarController else { completionHandler?(false); return }switch shortcutItem.type {case "favorites":tabController.selectedIndex = 0case "search":tabController.selectedIndex = 3case "contact":guard let url = URL(string: "mailto:\(AppGlobal.userDefaults[.email])") else { break }UIApplication.shared.open(url)default: break}completionHandler?(true)}
}// MARK: - User Notification Delegateextension AppDelegate {func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {guard let id = response.notification.request.content.userInfo["id"] as? Int,let link = response.notification.request.content.userInfo["link"] as? String,let url = try? link.asURL()else { return }switch response.actionIdentifier {case UNNotificationDefaultActionIdentifier: _ = navigateByURL(url)case "favorite": PostService().addFavorite(id)case "share": _ = navigateByURL(url)default: break}completionHandler()}private func scheduleUserNotifications(completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {// Get latest posts from server// Persist network manager instance to ensure lifespan is not interruptedurlSessionManager = PostService().updateFromRemote {guard case .success(let results) = $0 else { return completionHandler(.failed) }guard let id = results.created.first,let post = (try? Realm())?.object(ofType: Post.self, forPrimaryKey: id)else { return completionHandler(.noData) }var attachments = [UNNotificationAttachment]()// Completion process on exitfunc deferred() {// Launch notificationUNUserNotificationCenter.current().add(body: post.previewContent,title: post.title,attachments: attachments,timeInterval: 5,userInfo: ["id": post.id,"link": post.link],completion: {guard $0 == nil else { return Log(error: "Could not schedule the notification for the post: \($0.debugDescription).") }Log(debug: "Scheduled notification for post during background fetch.")})completionHandler(.newData)}// Get remote media to attach to notificationguard let link = post.media?.thumbnailLink else { return deferred() }let thread = Thread.currentUNNotificationAttachment.download(from: link) {defer { thread.async { deferred() } }guard $0.isSuccess, let attachment = $0.value else {return Log(error: "Could not download the post thumbnail (\(link)): \($0.error.debugDescription).")}// Store attachment to schedule notification laterattachments.append(attachment)}}}
}// MARK: - Internal functionsprivate extension AppDelegate {func setupTheme() {window?.tintColor = UIColor(rgb: AppGlobal.userDefaults[.tintColor])if !AppGlobal.userDefaults[.titleColor].isEmpty {UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor(rgb: AppGlobal.userDefaults[.titleColor])]}// Configure tab barif let controller = window?.rootViewController as? UITabBarController {controller.tabBar.items?.get(1)?.image = UIImage(named: "top-charts", inBundle: AppConstants.bundle)controller.tabBar.items?.get(1)?.selectedImage = UIImage(named: "top-charts-filled", inBundle: AppConstants.bundle)controller.tabBar.items?.get(2)?.image = UIImage(named: "explore", inBundle: AppConstants.bundle)controller.tabBar.items?.get(2)?.selectedImage = UIImage(named: "explore-filled", inBundle: AppConstants.bundle)if !AppGlobal.userDefaults[.tabTitleColor].isEmpty {UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor(rgb: AppGlobal.userDefaults[.tabTitleColor])], for: .selected)}}// Configure dark mode if applicableif AppGlobal.userDefaults[.darkMode] {UINavigationBar.appearance().barStyle = .blackUITabBar.appearance().barStyle = .blackUICollectionView.appearance().backgroundColor = .blackUITableView.appearance().backgroundColor = .blackUITableViewCell.appearance().backgroundColor = .clear}}
}
复制代码

看完后,有没有一个类就能完成整个应用的想法?今天,我们的目的就是使得AppDelegate这个类代码极限缩减。

如果大家有了解过微服务的话,大家就会知道,一个服务专职做一件事情,然后由网关来调度,这样的逻辑是非常清晰的,也非常便于维护,我们这次的改造也是源于这样的思路的。

按照上图,以后我们的AppDelegate只做网关对应的功能,其他具体业务,交由不同的服务去做,那么,我们应该如何实现这样的想法呢?

1.首先我们创建一个文件TDWApplicationDelegate.swift 里面的代码:

/// UIApplicationDelegate 协议扩展
public protocol TDWApplicationDelegate: UIApplicationDelegate {}
复制代码

这里定义了一个***TDWApplicationDelegate***,继承***UIApplicationDelegate***。这个协议是方便以后扩展用的。

2.我们再创建一个文件TDWAppDelegateService.swift 代码为:

import Foundationopen class TDWAppDelegateService: UIResponder, TDWApplicationDelegate {/// 启动服务的数组open var __services:[TDWApplicationDelegate] = []
}// MARK: - 启动
extension TDWAppDelegateService {open func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {__services.forEach {_ = $0.application?(application, didFinishLaunchingWithOptions: launchOptions)}return true}
}// MARK: - 其他应用唤起
extension TDWAppDelegateService {// iOS 9.0 及以下open func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {__services.forEach {_ = $0.application?(application, open: url, sourceApplication: sourceApplication, annotation: annotation)}return true}// iOS 9.0 以上open func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {if #available(iOS 9.0, *) {__services.forEach {_ = $0.application?(app, open: url, options: options)}return true}else {return false}}
}// MARK: - 前后台
extension TDWAppDelegateService {open func applicationWillEnterForeground(_ application: UIApplication) {__services.forEach { $0.applicationWillEnterForeground?(application) }}open func applicationDidEnterBackground(_ application: UIApplication) {__services.forEach { $0.applicationDidEnterBackground?(application) }}open func applicationDidBecomeActive(_ application: UIApplication) {__services.forEach { $0.applicationDidBecomeActive?(application) }}open func applicationWillResignActive(_ application: UIApplication) {__services.forEach { $0.applicationWillResignActive?(application) }}open func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {__services.forEach{ $0.application?(application, handleEventsForBackgroundURLSession: identifier, completionHandler: completionHandler)}}
}// MARK: - 退出
extension TDWAppDelegateService {open func applicationWillTerminate(_ application: UIApplication) {__services.forEach { $0.applicationWillTerminate?(application) }}open func applicationDidReceiveMemoryWarning(_ application: UIApplication) {__services.forEach { $0.applicationDidReceiveMemoryWarning?(application) }}
}// MARK: - 推送相关
extension TDWAppDelegateService {open func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {__services.forEach { $0.application?(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) }}open func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {__services.forEach { $0.application?(application, didFailToRegisterForRemoteNotificationsWithError: error) }}// NS_AVAILABLE_IOS(7_0);open func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {__services.forEach { $0.application?(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)}}
}// MARK: - 3DTouch相关
extension TDWAppDelegateService {@available(iOS 9.0, *)open func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {__services.forEach { $0.application?(application, performActionFor: shortcutItem, completionHandler: completionHandler) }}
}
复制代码

这个是本文的核心类,他主要做了些什么事情呢?

1.定义了一个服务数组,把服务都统一管理。 2.在extension里面实现常用的AppDelegate生命周期的协议。因为***__services***里面的服务都是继承于***TDWApplicationDelegate***,所以,没有服务,其实能实现AppDelegate生命周期。所以,在这个***TDWAppDelegateService***上,我在他所有的生命周期里同步遍历调用所有服务***__services***的对等生命周期,这样,就变相于我收到系统的信息后,会同步给各个服务,让他们自己处理了。

这样,我们就完成了整个服务的框架了。那么,我们如何使用呢? 这里,我以2个服务作为例子,当然,你可以构建10个,只要你喜欢。

import TDWAppDelegateServiceclass TDWInitializeService: NSObject, TDWApplicationDelegate {func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {print("TDWInitializeService")return true}
}class TDWLogService: NSObject, TDWApplicationDelegate {func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {print("TDWLogService")return true}
}
复制代码

这里有2个服务,一个是初始化服务,一个是日志服务,他们都只做一件事件,打印相关的字符串。

ok,下面我们构建下我们的AppDelegate:

import UIKit
import TDWAppDelegateService@UIApplicationMain
class AppDelegate: TDWAppDelegateService {var window: UIWindow?override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {// Override point for customization after application launch.__services = [TDWInitializeService(), TDWLogService()]return super.application(application, didFinishLaunchingWithOptions: launchOptions)}}
复制代码

AppDelegate非常简洁,他只有短短几句代码。 1.首先AppDelegate继承于***TDWAppDelegateService*** 2.然后重载***didFinishLaunchingWithOptions***方法,把服务实例放到***__services***数组就可以了。 3.最后,你就可以运行看结果了。

没错,服务按顺序执行对应的功能,也就是打印对应的字符串。

好了,以上就是本文要介绍的内容,欢迎评论反馈,谢谢!!

转载于:https://juejin.im/post/5cb97755518825328e00aac2

AppDelegate瘦身之服务化相关推荐

  1. AppDelegate瘦身指南

    原文链接:http://kyson.cn/index.php/archives/105/ AppDelegate瘦身是一个大家都很熟悉的话题,各家也有各自的解决方案.但方案无外乎两种,一种是从AppD ...

  2. AppDelegate的模块化+瘦身

    前言 关于iOS的模块化,要追溯到16年接触的BeeHive了,BeeHive将功能模块化,以module的形式进行构建,以performSelector:的形式进行module的事件响应,以prot ...

  3. iOS应用程序瘦身的静态库解决方案

    为什么要给程序瘦身? 随着应用程序的功能越来越多,实现越来越复杂,第三方库的引入,UI体验的优化等众多因素程序中的代码量成倍的增长,从而导致应用程序包的体积越来越大.当程序体积变大后不仅会出现编译流程 ...

  4. 容器定义存储(CDS)—存储技术的瘦身革命

     容器定义存储(CDS)-存储技术的"瘦身"革命 ICT架构师技术交流 2016-09-09 19:42 容器技术是最快被数据中心所广泛接受和采用的技术之一,从2013年起,据 ...

  5. [MaxCompute MapReduce实践]通过简单瘦身,解决Dataworks 10M文件限制问题

    用户在DataWorks上执行MapReduce作业的时候,文件大于10M的JAR和资源文件不能上传到Dataworks,导致无法使用调度去定期执行MapReduce作业. 解决方案: 第一步:大于1 ...

  6. SpringBoot 部署 Jar 文件,瘦身优化指南 !

    以下文章来源方志朋的博客,回复"666"获面试宝典 作者 | Java基基 来源 | https://mp.weixin.qq.com/s/Y5VK7TI1TQBN6O-k5O6h ...

  7. 如何给Docker镜像瘦身?

    在本文中,你将了解如何加快Docker构建周期并创建轻量级镜像.还是用比喻来说吧,给Docker镜像瘦身就跟我们减肥一样,减肥时期我们吃沙拉,拒绝披萨.甜甜圈和百吉饼. 这是备忘单. FROM:指定基 ...

  8. 可以卸载什么程序来对计算机进行瘦身,电脑越来越卡了,教你一分钟让电脑瘦身(C盘哪些文件可以删除)-怎么清理电脑内存...

    你的电脑是不是越来越慢? 这里让你10分钟学会给电脑软件瘦身,1分钟了解计算机硬件升级. 电脑运行越来越慢?10分钟学会电脑瘦身 一. 删除Update历史下载数据 删除此路径下的所有文件C:\\Wi ...

  9. 传真休眠怎么取消_C盘满了怎么办——系统瘦身

    系统瘦身 很多朋友在使用电脑时可能会发现一个问题,刚刚使用时,我们往往都把C盘(系统盘)预留几十个G左右的空间,而且可能装的东西并不是太多,但是磁盘却显示,可用空间只剩下10多个G,而且还有继续缩小的 ...

最新文章

  1. mybatis 使用resultMap实现数据库的操作
  2. 笔记-中项案例题-2019年下-整体管理
  3. Python 中的匿名函数,你滥用了吗?
  4. 02_Weblogic课程之安装篇:RedHat下JDK安装,RedHat下Weblogic安装,目录结构,环境变量设置
  5. 4.Vue 模板语法
  6. 计算机与人脑_类脑计算机:一种新型的计算系统
  7. 一会儿花雨停了的飞鸽传书
  8. 华为Mate 40系列或采用双处理器方案:国行版仍为麒麟芯
  9. Android使用HttpURLConnection下载图片
  10. Object类型转换成double/int类型
  11. 五十、Nginx负载均衡、SSL原理、生成SSL密钥对、Nginx配置SSL
  12. 「leetcode」491.递增子序列【回溯算法】详细图解!
  13. 苹果mac最好用的SVN客户端:Cornerstone 4 (SVN管理工具)
  14. Linux常用快捷键及命令
  15. 基于C51实现测试人体反应速度
  16. java所有单词_JAVA常用英语单词列表
  17. java.lang.IllegalArgumentException: Malformed \uxxxx encoding
  18. python真的能赚钱吗,学python可以赚钱吗
  19. 自媒体多平台矩阵怎么做?该如何管理自媒体矩阵?
  20. SCI论文从入门到精通

热门文章

  1. Html页面上输出不了PHP,在页面上直接输出未经解析的HTML源码
  2. win10树莓派改ip_Window 10通过网线和Wifi连接树莓派
  3. pythonrandrange_Python3 randrange() 函数
  4. 360浏览器卸载_陈蛋蛋碎碎念—如何完美地卸载流氓软件
  5. java项目经验怎么写_模具工简历项目经验怎么写
  6. HMM——前向后向算法
  7. 美国正面临“人才泡沫”破裂危机?
  8. 洛谷 P4011 孤岛营救问题【最短路+分层图】
  9. window screen (获取屏幕信息)
  10. 学习C# - Hello,World!