總在說的AppDelegate瘦身的另外一種思路
阿新 • • 發佈:2019-01-27
前段時間整理專案中的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>
的方法外不應該出現其他方法。