【问题标题】:viewDidLoad called before prepareForSegue finishes在 prepareForSegue 完成之前调用 viewDidLoad
【发布时间】:2013-02-15 08:32:33
【问题描述】:

我的印象是 viewDidLoad 将在 prepareForSegue 完成后被调用。这甚至是 Hegarty 教授斯坦福课程的方式(最近是 2013 年 2 月)。

但是,今天第一次,我注意到 viewDidLoad 在 prepareForSegue 完成之前被调用。因此,我在 prepareForSegue 中设置的属性不适用于目标 viewDidLoad 方法中的目标视图控制器。

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

更新

我刚刚弄清楚发生了什么。在我的destinationViewController 中,我有一个自定义设置器,每次更新“模型”时都会重新加载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 期间不会强制加载视图。

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

【问题讨论】:

  • 你怎么知道 viewDidLoad 被调用了?你能分享一些代码吗?
  • 我怀疑prepareForSegue 实际上是(直接或间接)调用viewDidLoad 的函数。

标签: ios storyboard segue viewdidload


【解决方案1】:

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

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

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

【讨论】:

  • 实际上如果你访问initWithCoder:中的outlets,它在调用prepareForSegue:之前会隐式调用viewDidLoad方法。感谢@Hampde123 的评论,这对我有帮助
  • 如果我们遵循这些规则,如何在视图控制器之间传递数据?
【解决方案2】:

我想对这里发生的事情做一点解释:

在视图显示之前调用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

【讨论】:

  • 这是有道理的,但是如果不是来自 prepareForSegue,你如何将参数传递给新视图?
  • 还是可以的,但是访问视图前需要设置参数
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    简单的解决办法是放置

    [self.tableView reloadData];
    

    viewWillAppear:

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          猜你喜欢
          • 2016-08-19
          • 2014-07-16
          • 2016-06-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多