2013-02-28 131 views
23

我的印象是viewDidLoad將在prepareForSegue完成後調用。甚至Hegarty如何教他的斯坦福大學課程(最近在2013年2月)。viewDidLoad在prepareForSegue完成之前調用

但是,今天第一次,我注意到viewDidLoad被稱爲之前prepareForSegue完成。因此,我在prepareForSegue中設置的屬性對目標viewDidLoad方法內的destinationViewController不可用。

這似乎與預期的行爲相反。

UPDATE

我只是想出了事情的原委。在我destinationViewController我有一個自定義的制定者,將每一個「模式」被更新時重新加載的tableView:

DestinationViewController  
- (void)setManagedObjectsArray:(NSArray *)managedObjectsArray 
    { 
     _managedObjectsArray = [managedObjectsArray copy]; 
     [self.tableView reloadData]; 
    } 

原來,由於destinationViewController是的UITableViewController的子類......叫「self.tableView」強制視圖加載。根據Apple的文檔,調用視圖控制器的視圖屬性可以強制視圖加載。 UITableViewController的視圖是tableView。

http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html

因此,在prepareForSegue下面一行是迫使destinationViewController的視圖加載:

vc.managedObjectsArray = <custom method that returns an array>; 

要解決這個問題,我改變了destinationViewController模型的定製的setter到:

- (void)setManagedObjectsArray:(NSArray *)managedObjectsArray 
    { 
     _managedObjectsArray = [managedObjectsArray copy]; 
     if ([self isViewLoaded]) { 
      [self.tableView reloadData]; 
     } 
    } 

如果tableView在屏幕上,這將只會重新加載tableView。因此不要在prepareForSegue時強制加載視圖。

如果有人反對這個過程,請分享您的想法。否則,我希望這可以防止一個人長時間不眠之夜。

+1

你怎麼知道viewDidLoad被調用?你能分享一些代碼嗎? – Spectravideo328 2013-02-28 23:24:38

+2

我懷疑'prepareForSegue'實際上是(直接或間接)調用'viewDidLoad'的函數。 – 2013-02-28 23:26:00

回答

2

感謝分享,幫我解決了我的問題。

在我的情況下,destinationViewController是一個的UITabBarController並修改它的viewControllers陣列觸發viewDidLoad中:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    UITabBarController *tabBarController = segue.destinationViewController; 
    tabBarController.viewControllers = ... 
    tabBarController.something = something; 
} 

在viewDidLoad中我需要東西要設置屬性,所以我不得不將它移到了:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    UITabBarController *tabBarController = segue.destinationViewController; 
    tabBarController.something = something; 
    tabBarController.viewControllers = ... 
} 
20

我曾經遇到類似的混亂。我學會了一般的經驗規則是:

  1. prepareForSegue的目的地VC的viewDidLoad
  2. viewDidLoad中調用之前只有在所有網點加載
  3. 不要試圖引用源VC的任何目的地VC的出口被稱爲prepareForSegue。

關於prepareForSegue的另一個教訓是避免多餘的處理。例如,如果您已經通過故事板將tableView單元格放到VC中,則如果您嘗試處理BOTH tableView:didSelectRowAtIndexPath和prepareForSegue,則可能會遇到類似的競爭條件。可以通過使用手動segue或放棄didSelectRowAtIndexPath中的任何處理來避免這種情況。

+0

事實上,如果你訪問'initWithCoder:'中的出口,它會在調用'prepareForSegue:'之前隱式調用'viewDidLoad'方法。感謝@ Hampde123爲您的評論提供幫助,幫助我順利完成任務 – cdescours 2017-04-07 09:09:28

1

簡單的解決辦法是把

viewWillAppear
[self.tableView reloadData]; 

1

想我會添加在這裏發生的事情一點解釋:

prepareForSegue被稱爲顯示視圖前

viewDidload被稱爲第一次訪問視圖。

可能發生的事情是您訪問view,prepareForSegue觸發手動加載視圖。

一般流動是:

  1. preformSegue
  2. prepareForSegue
  3. ViewController被添加到層級
  4. viewDidLoad

但是可能你的情況發生的情況是:

  1. preformSegue
  2. prepareForSegue
  3. | - 在prepareForSegue您訪問view
  4. | - view被自動加載=>viewDidLoad是被調用
  5. 從返回
  6. 視圖控制器被添加到等級,沒有viewDidLoad(已經調用)

所以,是平時的view屬性不是ViewController被添加到層次訪問之前,但如果是,viewDidLoad可以觸發早。

相關問題