前段時間整理項目中的AppDelegate
,發現很多寫在-
application:didFinishLaunchingWithOptions:
中的代碼都只是爲了在程序啓動時獲得一次調用機會,多爲某些模塊的初始化工作,如:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ... [FooModule setup]; [[BarModule sharedInstance] setup]; // ... return YES; } |
其實這些代碼完全可以利用Notification
的方式在自己的模塊內部搞定,分享一個巧妙的方法:
/// FooModule.m + (void)load { __block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification object:nil queue:nil usingBlock:^(NSNotification *note) { [self setup]; // Do whatever you want [[NSNotificationCenter defaultCenter] removeObserver:observer]; }]; } |
解釋:
+ load
方法在足夠早的時間點被調用- block 版本的通知註冊會產生一個
__NSObserver *
對象用來給外部 remove 觀察者 - block 對 observer 對象的捕獲早於函數的返回,所以若不加
__block
,會捕獲到 nil - 在 block 執行結束時移除 observer,無需其他清理工作
- 這樣,在模塊內部就完成了在程序啓動點代碼的掛載
值得注意的是,通知是在- application:didFinishLaunchingWithOptions:
調用完成後才發送的。
順便提下給 AppDelegate 瘦身的建議:AppDelegate 作爲程序級狀態變化的 delegate,應該只做路由和分發的作用,具體邏輯實現代碼還是應該在分別的模塊中,這個文件應該保持整潔,除了<UIApplicationDelegate>
的方法外不應該出現其他方法。