在prepareForSegue完成之前调用的viewDidLoad

我认为viewDidLoad会在prepareForSegue结束后被调用。 这就是Hegarty如何教他的斯坦福大学课程(最近在2013年2月)。

但是,今天我第一次注意到,在READForSegue完成之前调用了viewDidLoad。 因此,我在prepareForSegue中设置的属性不可用于目标viewDidLoad方法中的destinationViewController。

这似乎与预期的行为相反。

UPDATE

我只知道发生了什么事。 在我的destinationViewController中,我有一个自定义setter,每次更新“model”时都会重新加载tableView:

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

事实certificate,因为destinationViewController是UITableViewController的子类…调用’self.tableView’会强制加载视图。 根据Apple的文档,调用视图控制器的view属性可以强制加载视图。 UITableViewController的视图是tableView。

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

因此,在prepareForSegue中,以下行强制加载destinationViewController的视图:

 vc.managedObjectsArray = ; 

为了解决这个问题,我将destinationViewController模型的自定义setter更改为:

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

如果tableView在屏幕上,这只会重新加载tableView。 因此,在prepareForSegue期间不强制加载视图。

如果有人反对这个过程,请分享您的想法。 否则,我希望这可以防止一个人长时间不眠之夜。

我过去遇到过类似的困惑。 我学到的一般经验法则是:

  1. prepareForSegue在目标VC的viewDidLoad之前调用
  2. 只有在加载所有出口后才会调用viewDidLoad
  3. 不要尝试在源VC的prepareForSegue中引用任何目标VC的出口。

关于prepareForSegue的另一个经验教训是避免冗余处理。 例如,如果您已经通过故事板将tableView单元格转换为VC,则在尝试处理BOTH tableView:didSelectRowAtIndexPath和prepareForSegue时,可能会遇到类似的竞争条件。 可以通过使用手动segue或在didSelectRowAtIndexPath处放弃任何处理来避免这种情况。

谢谢分享,帮我解决了我的问题。

在我的例子中,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 = ... } 

简单的解决方案是放置

 [self.tableView reloadData]; 

viewWillAppear

以为我会对这里发生的事情添加一些解释:

在显示视图之前调用prepareForSegue

viewDidload在第一次访问视图时调用。

可能发生的是您在prepareForSegue访问了view ,触发了手动加载视图。

通常流程是:

  1. preformSegue
  2. prepareForSegue
  3. ViewController被添加到层次结构中
  4. viewDidLoad

但在你的情况下可能发生的事情是:

  1. preformSegue
  2. prepareForSegue
  3. | – 在prepareForSegue您可以访问该view
  4. | – view自动加载=> viewDidLoad被调用
  5. performSegue返回
  6. ViewController被添加到层次结构中,没有viewDidLoad (已经调用)

所以通常在将ViewController添加到层次结构之前不访问view属性,但如果是,则可以提前触发viewDidLoad