在iOS項目的開發中,AppDelegate是一個耦合發生的重災地,不少項目的開發時間一長,AppDelegate就不可避免地出現,代碼臃腫,調用順序混亂,邏輯複雜的問題。這個UIApplication的委託類,做爲一個常駐內存的單例,它承載了太多太多的功能,連蘋果的官方文檔都建議應該由AppDelegate來處理這些工做:git
不得不吐槽一句,有時候,蘋果的官方文檔的建議也不那麼靠譜啊🤦♀️。github
一個業務邏輯稍複雜點的項目,上述6點的全部功能的代碼直接一股腦塞到一個文件裏,能不臃腫纔怪了。c#
這裏介紹三種給AppDelegate瘦身的方式:bash
咱們知道一個app的各類事件發生時除了會調用UIApplicationDelegate中的方法,同時還會發送一個NSNotification,蘋果在UIApplication.h中聲明瞭這些通知。可是並非全部方法都有對應的通知,這時咱們能夠仿照蘋果的命名規範補上未定義的這些方法對應的通知,而後在本身的AppDelegate中顯式地發送它們。架構
好比,定義application:didRegisterUserNotificationSettings:
方法對應的通知:app
UIKIT_EXTERN NSNotificationName const UIApplicationDidRegisterUserNotificationSettingsNotification;
複製代碼
同時別忘了定義參數對應的key:模塊化
UIKIT_EXTERN NSString *const UIApplicationUserNotificationSettingsKey;
複製代碼
而後在AppDelegate中的application:didRegisterUserNotificationSettings:
方法裏執行:組件化
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationUserNotificationSettingsKey object:[UIApplication sharedApplication] userInfo:@{UIApplicationUserNotificationSettingsKey : notificationSettings}];
}
複製代碼
最後在須要響應這個事件的模塊中註冊通知,處理對應的業務邏輯便可。post
經過實現ModuleManager類,來管理項目中的模塊,首先在軟件啓動時經過讀取配置文件(一般用plist)讀取模塊,在AppDelegate的每一個事件接收到響應的時,在對應方法中逐一調用已註冊的模塊對應的響應方法: 首先在啓動時load modulesui
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[ModuleManager sharedInstance] loadModulesFromPlist:[[NSBundle mainBundle] pathForResource:@"modules" ofType:@"plist"]];
}
複製代碼
UIApplication event發生時,依次調用每一個module的對應方法:
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSArray<id<ModuleProtocol>> *modules = [ModuleManager sharedInstance].modules;
[modules enumerateObjectsUsingBlock:^(id<ModuleProtocol> _Nonnull module, NSUInteger idx, BOOL * _Nonnull stop) {
if ([module respondsToSelector:_cmd]) {
[module applicationDidBecomeActive:application];
}
}];
}
複製代碼
ModuleProtocol
繼承自UIApplicationDelegate
,定義以下:
@protocol ModuleProtocol <UIApplicationDelegate>
//在這裏根據本身項目的業務定義模塊的共有方法
@end
複製代碼
AOP在Objective-C中利用method swizzle來實現,例子就不舉了,相信有必定經驗的同窗應該都知道到底要如何實現。
以上三種方法,從結果上來講均可以達成給AppDelegate瘦身的目的,可是各有優缺點,所以也會用在不一樣場景,我說一下本身的我的見解,拋磚引玉:
以上三種方法,並無真正意義上的孰優孰劣,而是須要根據本身項目的特色來選擇更適合的方案。 最近在重構項目時,我結合AOP和NSNotification寫了一個小功能(https://github.com/jiaopen/AppDelegateExtensions),幾乎無侵入地解決AppDelegate臃腫問題。
AppDelegate
起名相同,所以須要在load
中顯式調用一行註冊代碼。UIApplicationDelegate
方法對應的通知,能夠根據自已業務的狀況補充。歡迎糾錯,拍磚。