【问题标题】:iOS Segue - When are the viewControllers InstantiatediOS Segue - viewControllers 何时实例化
【发布时间】:2013-01-14 11:31:11
【问题描述】:

我有一个简单的故事板,其中包含一个主视图控制器和两个详细视图控制器,如图所示。

问题 #1 - SequeA 将呈现 DetailA 的代码位于何处

问题 #2 - 在我的 AppDelegate 代码中,我需要创建一个包含应用程序中所有 ViewController 的数组 - 我怎样才能获得该数组? - 它在故事板中,但我如何以编程方式访问它。

我可以通过执行以下操作来获取 MainViewController - myViewControllerMain = (ViewControllerMain*) self.window.rootViewController;

但我不知道如何访问详细视图控制器 (a & b)

问题#3 - DetailA 是在 MainViewController 被实例化时被实例化,还是在 Seque 被“触发”时被实例化(这里正确的词是什么 - 调用?)

【问题讨论】:

  • 我查看了 rayWenderlich 链接。那里有一个参考可以访问主视图控制器 - 但我已经知道了。 AFAIK - 它没有解决如何到达其他视图控制器。由于我没有使用导航控制器 - 故事板中必须有一些东西告诉我所有其他 viewController 是什么。
  • 我会添加一个答案,因为 cmets 中没有空间
  • 我试图在下面回答您的问题,但我不得不承认,这些问题本身会引发问题。为什么 A 或 B 需要知道视图控制器列表?你能解释一下你想做什么吗?我可能会根据您的问题推断这是自定义容器视图控制器的候选者(这是一个与我们所有人都回答的非常不同的主题),但您必须更详细地解释主人在做什么, A 和 B 在做什么,等等。你能用不太抽象的术语来描述工作流或业务逻辑吗?我们将能够提供更具建设性的建议。

标签: ios uiviewcontroller segue


【解决方案1】:

如果您阅读该链接,您会明白没有代码可以按照您的要求执行 segue。 . . XCode / Interface Builder)不是代码生成器,如果您使用其他语言的界面构建器,您可能会理解它,它不是为您编写代码,因此找不到。话虽如此,您可以通过编程方式调用 segue。

至于列出 ViewControllers,我不相信有办法以您希望的方式做到这一点。 ViewController 只是特定类型的类。您唯一能做的就是获取所有已加载类的列表并通过检查它们是否是视图控制器进行迭代,但这会很慢,我不确定您为什么要这样做,毕竟这是唯一的方法将执行的代码将包含在您的项目中,您肯定知道您的项目中有哪些代码?

在执行 segue 时实例化视图控制器。

【讨论】:

  • 感谢您的澄清 - 我来自 .Net/C#,这个概念略有不同。
【解决方案2】:

1) 如果您在 IB 中连接它,则没有代码(除了描述情节提要的 XML 文件)。

2) 在实例化它们之前,您无法访问其他控制器。

3) 在执行 segue 时实例化。

为什么认为您需要在应用委托中创建一个包含所有控制器的数组?

【讨论】:

    【解决方案3】:

    你问:

    问题 #1 - SegueA 将呈现 DetailA 的代码在哪里?

    如果您以编程方式调用 segue A(例如调用 performSegueWithIdentifier),则该代码位于主视图控制器中。但是,通常,您根本不需要以编程方式调用它,因为当您在 Interface Builder 中创建 segue 时,您通常会从某个控件(例如主视图中的按钮)链接它,因此您不需要必须以编程方式执行任何操作来启动 segue。但是,当您调用 segue A 时,在主视图控制器中会调用可选的关联 shouldPerformSegueWithIdentifier(适用于 iOS 6 及更高版本)和 prepareForSegue

    问题 #2 - 在我的 AppDelegate 代码中,我需要创建一个包含应用程序中所有 ViewController 的数组 - 我怎样才能获得该数组? - 它在故事板中,但我如何以编程方式访问它。

    我可以通过执行以下操作来获取 MainViewController -

    myViewControllerMain = (ViewControllerMain*) self.window.rootViewController;
    

    但我不知道如何访问详细视图控制器 (a & b)

    通常您不需要维护视图控制器数组(自定义容器视图控制器可能例外,即使这样,有时您也不必自己做)。但是,如果您需要访问应用程序委托的某些属性,您可以执行以下操作:

    YourAppDelegate *appDelegate = (YourAppDelegate *)[UIApplication sharedApplication].delegate;
    // you can now access properties of the `appDelegate`
    

    话虽如此,我很难想到细节控制器 A 或细节控制器 B 从主控制器检索视图控制器列表的情况。您确实应该解释您要解决的业务问题。通常你会做一些委托协议或使用一些通知过程。它根据您要解决的问题而有所不同。但是,如果 A 或 B 需要从 master 获取视图控制器列表,您应该仔细检查您的设计。

    问题#3 - DetailA 是在 MainViewController 被实例化时被实例化,还是在 Seque 被“触发”时被实例化(这里正确的词是什么 - 调用?)

    除了自定义容器和/或嵌入 segue,基本流程是:

    • segue 被触发;
    • shouldPerformSegueWithIdentifier 在 iOS 6 中是可选调用的,如果 NO 则我们在这里停止;
    • 目标控制器已实例化;
    • 调用prepareForSegue,允许您将信息从源控制器传递到目标控制器;
    • 然后创建与目标视图控制器关联的视图;
    • 调用目标中的viewDidLoad(带回家的消息是,在此之前不要尝试操作此目标视图中的视图/控件,例如源的prepareForSegue);
    • 只有这样,目标视图才能完成其布局、外观调用等。

    参考资料:

    【讨论】:

    • 感谢您的详细回复。有没有办法获得 SegueIdentifiers 的列表。在故事板中,我的 MainView 通过 Segue 连接到 ViewA。在 InterfaceBuilder 中,为 segue 提供了一个字符串标识符。我不想在我的代码中对该字符串进行硬编码,而只是检查是否调用了 Segue“X”。 Segue X 是一个对象——我为什么要依赖一个字符串来查询调用了什么 Seque。
    • @OneGuyInDc 没有持久的 Segue X 对象。无论如何,shouldPerformSegueWithIdentifierperformSegueWithIdentifier only 有标识符字符串,所以没有其他东西可以使用。而prepareForSegue 中的UIStoryboardSegue 对象在您每次执行时都会重新实例化,因此您无法比较它们。 identifier 是建议的技术。另一种方法是对 segue 进行子类化并查看类成员资格,但这需要大量额外的工作,并且会严重降低可读性,并没有真正的好处。
    • DetailViewControllerA 或 DetailViewControllerB 何时“被破坏”? (对不起我的 C++ 根源)换句话说,在 DetailViewControllerB 我有一个按钮,单击该按钮时会执行 [self dismissViewControllerAnimated:NO completion:nil];上面的行是否破坏了 DetailViewControllerB.我认为这不会发生。
    • @OneGuyInDc 假设您没有在其他地方维护对这些控制器的强引用,当您调用 popViewControllerAnimateddismissViewControllerAnimated 时,视图控制器将被释放(取决于您是否使用了 push segue 或模态序列,分别)。您可以通过为您的两个控制器编写自己的 dealloc 方法来验证这一点,例如,- (void) dealloc { NSLog(@"%s", __FUNCTION__); } 如果您这样做,您的控制器会告诉您何时释放它。 (顺便说一句,我假设您使用的是 ARC。)
    • dealloc 未被调用 - 以下如何创建强引用 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"analog "]) { ViewControllerAnalog *vca = segue.destinationViewController; vca.AnalogVoltageA = myAnalogVoltageADataPoint; vca.AnalogVoltageB = myAnalogVoltageBDataPoint; } else if ([segue.identifier isEqualToString:@"temperature"]) { ViewControllerTemperature *vcb = segue.destinationViewController; vcb.TemperatureDataPoint = myTemperatureDataPoint; } }
    猜你喜欢
    • 1970-01-01
    • 2020-02-27
    • 2011-11-27
    • 2017-04-27
    • 2013-04-27
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多