3

我对 iOS 开发完全陌生,但仍然不知道如何完成如此简单的任务。

我有一个原始的 xCode 4.4.1“单一视图应用程序”项目。

例如,我想要四个屏幕,每个屏幕都有用于切换到其他视图的按钮。

屏幕不是按层次设置的:例如,我希望能够从屏幕 1 切换到屏幕 2 或屏幕 3,从屏幕 2 切换到屏幕 4,等等。在应用程序运行时——显示第一个屏幕,但它的状态不是“root”或“main”——它只是一个常见的屏幕。

我的条件是:

  1. 我只有默认的主故事板文件(xib 解决方案不好)。
  2. 我不想依赖使用导航控制器或类似的预结构化的东西。

在我看来,我需要以某种方式设置带有子控制器的容器控制器,如 WWDC 2011 的 Session 102 中所述,但我不明白如何正确编写代码,因此它不会与主 Storyboard 冲突(我有两次尝试使用来自其他类似主题的基于 xib 的解决方案,但都失败了)。

我非常感谢一个完整的工作示例,因为我的经验还不允许我依赖部分提示,尽管它们也可以。

首选以编程方式执行此操作的解决方案(不使用拖动等 xCode UI 功能)。

谢谢!

更新:切换时,我不想每次都实例化新屏幕,而是重新使用现有的屏幕,如果它们已经存在的话。

更新 2:我的用例,针对这个问题进行了简化:

我有一个注册屏幕,带有相应的模式屏幕来处理所有常见的登录/注销/等情况。我有我的应用程序的主屏幕,在登录/注册程序完成后成为“主”应用程序屏幕。我不想让注册屏幕/控制器成为主屏幕的模式,因为主屏幕很大程度上取决于用户特定的信息,所以我希望这些屏幕不以任何方式按层次结构组织。对于这种简化的情况,我考虑采用以下流程:

1) 用户尚未登录 - 显示注册屏幕。后来,在注册之后。程序完成 -切换到“主”屏幕(这是我不知道的关键点,这就是为什么这个问题)。

2) 用户已登录并被应用程序识别 - 出现“主”屏幕。

像我描述的那样具有注册和“主”屏幕排除(或什么?)在“选项卡式应用程序”模板中具有“选项卡控制器”功能的情况,因为在我的情况下,我希望完全禁用选项卡栏 - 我需要什么不是导航。和导航栏功能,但只是在 reg 之间执行转换的方式。和“主”屏幕-这就是我在问题中“用手”的意思。

最后更新:

在试验了标签栏控制器之后,对于这个用例,我最终使用了禁用导航栏的导航控制器(我在标签栏控制器中没有找到类似的控制器)并通过performSegueWithIdentifier方法管理屏幕切换以及切换他们通过“手动”操作viewControllers导航堆栈。

谢谢大家的回答!

4

2 回答 2

2

可能最简单的做法是在情节提要中使用 segues。

右键单击并从主视图控制器拖动到其他每个控制器。它将询问要创建哪种类型的 segue,并选择模态。

然后,确保在标识符属性中为每个 segues 提供一个唯一的标识符字符串。

现在,从代码中,只要您希望其中一个视图控制器处于活动状态,您就可以调用

[self performSegueWithIdentifier:@"Foo Segue" sender:(id)sender];

上面的 sender 对象可以是您想要的任何东西,通常是您想要传递给准备显示的视图控制器的一些信息。

现在,就在显示 segue 之前,无论是通过编程方式还是直接来自故事板定义的交互,prepareForSegue都会调用该方法。因此,您将再次在“主”视图控制器的代码中执行类似的操作。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // You have access to the view controller that is getting ready to be
    // displayed, as well as the identifier, so you can set values or whatever
    // before the view controller is presented.
    if ([segue.identifier isEqualToString:@"Foo Segue"]) {
        FooViewController *vc = segue.destinationViewController;
        // The view controller is completely instantiated, and you can do any
        // setup work, like setting property values on the view controller
        // to give it its model, or whatever else you want to do.
    }
}

现在,您需要一些方法来知道该控制器何时完成。这可以通过多种方式完成。呈现的视图控制器可以关闭自己,或者可以使用委托或通知来告诉呈现的视图控制器已经完成并且应该被关闭。

在您的情况下,让提供的 VC 自行解散可能很好。所以,只要打电话

[self dismissViewControllerAnimated:YES completion:nil];

如果您不想使用 segue,则可能必须直接从情节提要中加载 VC(或给它们自己的 nib)。要从情节提要中实例化,您必须为要实例化它们自己的标识符标签的视图控制器提供(再次查看属性窗格并在 VC 上设置属性)。

然后你可以这样做(假设包含此代码的 VC 与它试图实例化的 VC 在同一个情节提要中)......

FooViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"FooViewController"];

然后,您实际上向该控制器展示...

[self presentViewController:vc animated:YES completion:nil];

当然,还有其他几种方法可以做到这一点,每种方法都有一些优点/缺点。我建议您使用它并阅读相关文档,以便您可以就使用哪种方法做出明智的决定。

无论如何,以上内容应该为您提供了一条通向目标的简单途径。

于 2012-08-11T13:52:55.927 回答
2

您的问题的简短回答是使用标签栏控制器。这是一个表面上简单的控件,实际上管理了很多复杂性,重新实现它对于初学者或应用程序的用户来说不是一个好主意,他们将习惯于标签栏控制器的工作方式。

标签栏控制器有一个属性 ( viewControllers),您可以通过控制拖动到其他场景来在情节提要中填充该属性。标签栏控制器询问这些视图控制器中的每一个以构建标签栏(名称和图像,适当数量的项目,“更多”控制器,如果有太多无法容纳在栏上)并处理它们之间的切换,更改包含的视图和选项卡栏的大小以处理旋转事件。因此,标签栏控制器的视图包含两个子视图 - 一个用于保存标签栏,另一个用于保存当前显示的视图控制器的视图。

您需要自己复制所有这些功能,这对于初学者来说非常复杂,而且肯定超出了 Stack Overflow 答案的范围。您将复制现有功能这一事实也应该是一个危险信号,表明您是否真的应该以这种方式工作。

故事板也不支持自己实现标签栏类型的控制器,因为自定义容器视图控制器无法使用关键部分(“关系 - 视图控制器”)。因此,您必须在代码中设置您的 UI 并手动实例化视图控制器以建立关系,这很可能与您的主故事板发生冲突 - 尽管您关于更喜欢以编程方式执行此操作的句子与故事板请求中的冲突问题标题,所以我对此有点困惑。

如果您仍然想要,简要概述如何实现此功能:

  • 创建自定义 UIViewController
  • 添加一个 viewControllers 属性,以及一些处理切换的控件,可能是一个分段控件
  • 设置viewControllers属性后,将标题设置为分段控制段之一的标题。将数组中第一项的视图添加为主视图的子视图(使用适当的框架,因此它不会覆盖您的分段控件)并使用 and 将其添加为子视图[self addChildViewController:vc]控制器[vc didMoveToParentViewController:self]
  • removeFromSuperview当分段控件的值发生变化时,从视图层次结构 ( ) 和视图控制器层次结构 ( )中删除当前视图控制器的视图removeFromParentViewController,并使用上面的代码添加新选择的视图控制器的视图。
于 2012-08-12T08:23:06.077 回答