AppDelegate解耦
作為iOS整個專案的核心App delegate
,隨著專案的逐漸變大,會變得越來越臃腫,一不小心程式碼就過了千行.
大型專案的App delegate
體積會大到什麼程度呢?我們可以參考下國外2億多月活的Telegram
的ofollow,noindex">App delegate
.是不是嚇一跳,4千多行.看到這樣的程式碼是不是很想點選左上角的x.
是時候該給App delegate
解耦了,目標:
每個功能的配置或者初始化都分開,各自做各自的事情.App delegate
要做到只需要呼叫就好了.
下面來談談如何利用兩種設計模式實現:
1.命令模式
命令模式: 傳送方傳送請求,然後接收方接受請求後執行,但傳送方可能並不知道接受方是誰,執行的是什麼操作,這樣做的好處是傳送方和接受方完全的鬆耦合,大大提高程式的靈活性.
1. 定義好協議,把相關初始化配置程式碼分類
protocol Command { func execute() } struct InitializeThirdPartiesCommand: Command { func execute() { // 第三方庫初始化程式碼 } } struct InitialViewControllerCommand: Command { let keyWindow: UIWindow func execute() { // 根控制器設定程式碼 } } struct InitializeAppearanceCommand: Command { func execute() { // 全域性外觀樣式配置 } } struct RegisterToRemoteNotificationsCommand: Command { func execute() { // 遠端推送配置 } } 複製程式碼
2. 管理者
final class StartupCommandsBuilder { private var window: UIWindow! func setKeyWindow(_ window: UIWindow) -> StartupCommandsBuilder { self.window = window return self } func build() -> [Command] { return [ InitializeThirdPartiesCommand(), InitialViewControllerCommand(keyWindow: window), InitializeAppearanceCommand(), RegisterToRemoteNotificationsCommand() ] } } 複製程式碼
3.App delegate
呼叫
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { StartupCommandsBuilder() .setKeyWindow(window!) .build() .forEach { $0.execute() } return true } 複製程式碼
使用命令模式的好處是,如果要新增新的配置,設定完後只要加在StartupCommandsBuilder
中就可以了.App delegate
中不需要新增任何內容.
但這樣做只能將didFinishLaunchingWithOptions
中的程式碼解耦,App delegate
中的其他方法怎樣解耦呢?
2.組合模式
組合模式: 可以將物件組合成樹形結構來表現"整體/部分"層次結構. 組合後可以以一致的方法處理個別對象以及組合物件.
這邊我們給App delegate
每個功能模組都設定一個子類,每個子類包含所有App delegate
的方法.
1. 每個子模組實現各自的功能
// 推送 class PushNotificationsAppDelegate: AppDelegateType { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { print("推送配置") return true } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { print("推送相關程式碼...") } // 其餘方法 } // 外觀樣式 class AppearanceAppDelegate: AppDelegateType { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { print("外觀樣式配置") return true } } // 控制器處理 class ViewControllerAppDelegate: AppDelegateType { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { print("根控制器設定程式碼") return true } } // 第三方庫 class ThirdPartiesConfiguratorAppDelegate: AppDelegateType { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { print("第三方庫初始化程式碼") return true } func applicationDidEnterBackground(_ application: UIApplication) { print("ThirdPartiesConfiguratorAppDelegate - applicationDidEnterBackground") } func applicationDidBecomeActive(_ application: UIApplication) { print("ThirdPartiesConfiguratorAppDelegate - applicationDidBecomeActive") } } 複製程式碼
2. 管理者
typealias AppDelegateType = UIResponder & UIApplicationDelegate class CompositeAppDelegate: AppDelegateType { private let appDelegates: [AppDelegateType] init(appDelegates: [AppDelegateType]) { self.appDelegates = appDelegates } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { appDelegates.forEach { _ = $0.application?(application, didFinishLaunchingWithOptions: launchOptions) } return true } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { appDelegates.forEach { _ = $0.application?(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) } } func applicationDidEnterBackground(_ application: UIApplication) { appDelegates.forEach { _ = $0.applicationDidEnterBackground?(application) } } func applicationDidBecomeActive(_ application: UIApplication) { appDelegates.forEach { _ = $0.applicationDidBecomeActive?(application) } } } 複製程式碼
3.App delegate
呼叫
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? let appDelegate = AppDelegateFactory.makeDefault() enum AppDelegateFactory { static func makeDefault() -> AppDelegateType { return CompositeAppDelegate(appDelegates: [ PushNotificationsAppDelegate(), AppearanceAppDelegate(), ThirdPartiesConfiguratorAppDelegate(), ViewControllerAppDelegate(), ] ) } } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { _ = appDelegate.application?(application, didFinishLaunchingWithOptions: launchOptions) return true } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { appDelegate.application?(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) } func applicationDidBecomeActive(_ application: UIApplication) { appDelegate.applicationDidBecomeActive?(application) } func applicationDidEnterBackground(_ application: UIApplication) { appDelegate.applicationDidEnterBackground?(application) } } 複製程式碼
在App delegate
解耦中相比命令模式,使用組合模式的可自定義程度會更高一點.
本文收錄於SwiftTips" rel="nofollow,noindex">SwiftTips