0

我已經閱讀了一堆關於SO的答案,但我有點困惑。查看控制器,依賴注入和init/viewDidLoad

我有我創建的標籤欄控制器子類,並在其viewDidLoad,我創建每個視圖控制器。但是,我有一個依賴關係,我將它傳遞給父級,然後依次進入每個選項卡的視圖控制器。我使用自定義的init方法(頭文件中爲它聲明瞭NS_DESIGNATED_INITIALIZER)傳遞該依賴項。但是,它看起來像[super init]直接觸發了viewDidLoad,因此在創建其他視圖控制器時依賴性設置不正確。

這裏是我的自定義init方法:

- (instancetype)initWithSession:(T2Session *)session 
{ 
    self = [super init]; 

    if (self) { 
     _session = session; 
    } 

    return self; 
} 

我想session由我創建視圖控制器的時間設置,但我有點困惑如何做到這一點的最好辦法是。任何意見非常感謝。提前致謝!

+0

調用init不會導致調用viewDidLoad。第一個選項卡中的控制器會調用viewDidLoad方法,因爲選項卡欄控制器會將該控制器的視圖添加到其視圖中。除非您點擊其選項卡,否則其他控制器都不應調用viewDidLoad。 – rdelmar 2015-02-08 21:05:29

+0

嗯......我在我的標籤欄控制器的viewDidLoad中設置了一個斷點,並且堆棧跟蹤直接指向了我的'self = [super init];'行... – Mason 2015-02-08 21:25:26

+0

任何控制器中的Init都不應該直接導致視圖正在加載。在標籤欄控制器的情況下,它的視圖被系統加載(以某種方式),因爲它是窗口的rootViewController,並且導致調用viewDidLoad。 – rdelmar 2015-02-08 22:29:22

回答

1

我以前遇到過這種情況。
你可能坐在那裏(像我一樣)希望viewDidLoad沒有得到這麼快打電話。

無論如何,這是我看中了:

- (instancetype)initWithSession:(T2Session *)session { 

    if (self = [super init]) { 
     self.session = session; 
    } 

    return self; 
} 

- (void)setSession:(T2Session *)session { 
    _session = session; 

    ... call the setup methods here, instead of viewDidLoad 
} 

起初我以爲這打破不能從初始化中調用self.xxxx金科玉律
但是,我覺得這個規則只有在調用IBOutlets上可能還沒有連線的方法時才真正相關。
在這種情況下,T2Session *session不是筆尖插座。

或者,如果您不想違反該規則,您可以隨時刪除自定義初始化程序..並恢復爲使用常規屬性注入而不是構造函數注入。例如

T2Session *session = ..... 

MYTabBarController *tabBarController = [[MYTabBarController alloc] init]; 
[tabBarController setSession:session]; 

這些只是我的想法,希望它有幫助。

+0

也確保您在setSession的開頭調用_session = session:方法 – MDMonty 2015-03-10 23:04:07

+0

真棒,感謝您的建議!仍然沒有做任何事情,但我會考慮更多。 – Mason 2015-03-12 05:03:03