在prepareForSegue完成之前调用的viewDidLoad

时间:2013-02-28 23:20:09

标签: ios storyboard segue viewdidload

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

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

这似乎与预期行为相反。

更新

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

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

事实证明,因为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 = <custom method that returns an array>;

要解决此问题,我将destinationViewController模型的自定义setter更改为:

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

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

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

6 个答案:

答案 0 :(得分:23)

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

  1. 在目标VC的viewDidLoad
  2. 之前调用prepareForSegue
  3. 仅在加载所有商店后调用viewDidLoad
  4. 请勿尝试在源VC的prepareForSegue中引用任何目标VC的出口。
  5. 关于prepareForSegue的另一个经验教训是避免冗余处理。例如,如果您已经通过故事板将tableView单元格转换为VC,则在尝试处理BOTH tableView:didSelectRowAtIndexPath和prepareForSegue时,可能会遇到类似的竞争条件。可以通过使用手动segue或在didSelectRowAtIndexPath处放弃任何处理来避免这种情况。

答案 1 :(得分:2)

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

在我的例子中,destinationViewController是一个UITabBarController并修改它的viewControllers数组触发了viewDidLoad:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    UITabBarController *tabBarController = segue.destinationViewController;
    tabBarController.viewControllers = ...
    tabBarController.something = something;
}
在viewDidLoad中我需要设置 something 属性,所以我不得不将其移动:

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

答案 2 :(得分:2)

我想在此处添加一些解释:

在显示视图之前调用

prepareForSegue

viewDidload在第一次访问视图时被调用(视图是延迟加载的)。

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

通常流程是:

  1. preformSegue
  2. prepareForSegue
  3. ViewController已添加到层次结构
  4. viewDidLoad
  5. 但你的情况可能发生的事情是:

    1. preformSegue
    2. prepareForSegue
    3. | - 在prepareForSegue您访问view
    4. | - view自动加载=&gt; viewDidLoad已被调用
    5. performSegue
    6. 返回
    7. ViewController已添加到层次结构中,没有viewDidLoad(已调用)
    8. 所以通常在view添加到层次结构之前不会访问ViewController属性,但如果是,则可以提前触发viewDidLoad

答案 3 :(得分:1)

简单的解决方案是放置

[self.tableView reloadData];
viewWillAppear中的

答案 4 :(得分:0)

我的动态单元格也有类似的问题,该单元格在选择时显示出模态。 prepareForSeguedidSelect:atIndexPath之前执行。帮助我的是,在情节提要中,我将任务重新分配为从控制器而不是动态单元原型开始。我解决了比赛条件(?),一切运行正常!

答案 5 :(得分:0)

在我的情况下,在prepareSegue 中设置目标presentationController 的委托导致调用viewDidLoad。 我搬家了 segue.destination.presentationController?.delegate = self 到 prepareSegue 结束:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?)     {
    // do stuff ....
    segue.destination.presentationController?.delegate = self
     }