以编程方式在iOS中导航

时间:2011-03-24 12:56:04

标签: iphone objective-c ios ipad uiviewcontroller

我正在将现有的Android应用移植到iOS,我在这种环境中缺乏经验。我到目前为止用于导航多个视图的示例都使用某种可视化用户控件来触发视图的加载和卸载(标签栏,导航栏)。此应用程序的导航需要非常严格,不允许用户在三个视图之间自由移动。

应用程序需要具有全屏幕初始视图,用户与之交互的主视图以及用于数据收集的第三个视图。应该出现启动画面,当点击启动图像时,应该将用户导航到主视图。主视图控制器中将有自定义逻辑,用于确定是否需要数据,它应该导航到数据收集视图。输入有效数据并且用户单击“确定”后,它应该导航回主视图。

到目前为止我所看到的是所有视图都应该有一个关联的UIViewController类,这样做的简单方法是一次创建XIB和UIViewController类并将它们链接在一起(我有很多示例/书籍/我可以参考该部分的教程)。我相信我读过的应用程序应该有一个根UIViewController,它可以处理加载其他人并在它们之间导航。

我的问题是: 我应该从我用于加载其他视图控制器的主视图控制器派生出什么类? 如何将其连接到应用程序,以便它知道将其加载为主控制器? 在应用程序中使用导航控制器并允许其他视图获取对它的引用的公认标准方法是什么?我的UIViewControllers是否应该拥有对其父控制器的引用,还是应该在需要时向UIApplication请求引用它?如何确保在用户导航时不会实例化视图及其控制器的额外副本?

5 个答案:

答案 0 :(得分:7)

听起来你可以用几个基本的电话完成你需要的东西。以编程方式调用视图控制器:

- (void)showController {
    MyViewController *myController = [[MyViewController alloc] initWithNibName:@"MyViewControllerXIB" bundle:nil];

    [self.navigationController pushViewController:myController animated:YES];
    [myController release];
}

要返回上一个视图,只需从任何视图控制器调用:

- (void)goBack {
    [self.navigationController popViewControllerAnimated:YES];
}

阅读UINavigationController的文档,了解更多浏览视图的方法。此方法只是执行此操作的众多方法之一,可能并不适合所有情况。

答案 1 :(得分:7)

  

我应该从我的课程中得到什么课程   我用的主视图控制器   加载其他人?

的UIViewController

  

如何将其连接到应用程序   它知道加载这个作为主要   控制器?

阅读the "Defining Your Subclass" section of View Controller Programming Guide for iOS。抓一点 - 读完整件事。这一切都很重要,你现在也可以开始学习它。另请阅读适用于iOS的应用程序编程指南。再次阅读整篇文章,但the application lifecycle part与您的问题最相关。

  

什么是公认的标准方式   在中有一个导航控制器   应用程序并允许其他视图   获得它的参考?

同样, View Controller Programming Guide 中对此进行了解释。视图永远不应关心导航控制器,但属于导航堆栈的任何视图控制器都可以通过各自的navigationController属性直接访问导航控制器。

  

我的UIViewControllers应该持有   引用他们的父控制器,   或者他们应该问UIApplication   在需要时参考它?

视图控制器已在其(surprise!)parentController属性中引用其父控制器。控制器最好避免对它做太多假设 但是父母。如果控制器期望其父级是某种类型或响应某些消息,则重用该控制器或重新组织应用程序变得更加困难。尝试给控制器创建它时需要做的事情。如果控制器需要请求额外的数据或类似的东西,委托是一个很好的方法。

  

如何确保不实例化   额外的意见副本及其副本   用户导航时的控制器?

谨慎行事。在正确结构化的应用程序中创建额外的视图副本没有太大的危险,因为每个视图控制器都应该处理自己的视图。如果您发现自己在拥有它们的视图控制器的上下文之外加载或以其他方式创建视图,请停止它。

答案 2 :(得分:3)

不太对 - 每个UIViewController都应该知道如何触发它的子节点。 Apple通过视图的首选导航路径是分支树,标签栏的警告将多个视图控制器折叠到树上的单个节点中。

您没有明确处理加载。通常,您的NIB之间有足够的关系,容器类会自动加载。然后Cocoa将在需要时加载视图但尚未加载(这是loadView和viewDidLoad的目的),并保留它们,除非并且直到低内存警告要求它们被清除(导致viewDidUnload)。您自己显式加载NIB是相对罕见的(尽管表视图单元格是一个明显的例子,其中以编程方式加载NIB非常常见)。

所以你可能有:

  • 启动画面或第一个视图控制器的预览,作为Default.png
  • 一个可能显示Default.png的视图控制器,并且有两个出口连接到数据采集控制器和主控制器
  • 当用户点击主屏幕上的按钮时,询问模型是否需要数据收集。如果是,则导航到数据收集控制器,否则导航到主控制器
  • 将数据采集控制器作为主控制器的插座,让它在适当的时刻执行导航

在创建基于视图的新项目时,您可以免费获得MainWindow.xib。可能最简单的方法是在那里放置对三个UIViewController子类的引用,但是将它们中的每一个设置为从其他文件加载。在MainWindow.xib中设置它们之间的链接,在相关XIB中的相关视图中设置链接。

这将阻止你保留任何控制器的多个实例,内置的Cocoa加载机制将确保占用大量内存的东西 - 视图 - 仅按需加载并保持不超过空间允许。

无需链接到父视图控制器。每个视图控制器都已通过parentViewController属性知道是谁呈现它。因此,如果视图控制器想要解雇自己并返回给出任何人,那么你可以发出:

[self.parentViewController dismissModalViewControllerAnimated:YES];

因为该模型理想情况下是一个独立的主权事物,所有控制器确实需要知道它们可以呈现哪些其他控制器,如何从模型中填充自己以及如何将数据推送回模型。您很少会在视图控制器之间找到特别复杂的链接。

答案 3 :(得分:0)

我认为您应该在应用程序委托中加载/卸载视图,然后每个视图都应该向应用程序委托发送通知。

以下是Apple的官方介绍:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Notifications/Introduction/introNotifications.html

答案 4 :(得分:0)

您可以先设置ViewController首先加载 如果应用程序是基于导航的,请使用以下代码:

<强> AppDelegate.m

  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  {
    MainViewController *mainViewController = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
    self.nav = [[UINavigationController alloc] initWithRootViewController:mainViewController];
    [_window addSubview:nav.view];
    [_window makeKeyAndVisible];
  }

如果应用程序是基于View的,请使用以下代码:

  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
  }