1. 程式人生 > >總在說的AppDelegate瘦身的另外一種思路

總在說的AppDelegate瘦身的另外一種思路

前段時間整理專案中的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>的方法外不應該出現其他方法。