如何在没有导航控制器的情况下使用多个iOS自定义视图控制器

8

我正在开发一款应用程序,其中使用了多种类型的屏幕,每个屏幕都需要自己的自定义视图控制器。我成功地通过在我的应用程序委托中重新分配主windowrootViewController方法来在视图控制器和相关视图之间进行切换,代码如下:

- (void)changeRootViewController:(NSString *)controllerName
{
    if (controllerName == @"book") {
        rootViewController = (UIViewController *)[[BookViewController alloc] init];
        [self.window setRootViewController:rootViewController];
    } else if (controllerName == @"something_else") {
        // Use a different VC as roowViewController
    }
}

我这样做的方式似乎不是最佳实践。 我也不想使用UINavigationControllerUITabBarController作为rootViewController。 这样做是错误的吗?如果是,我应该如何更改方法?
我以为这个问题已经有答案了,但我已经在Google上搜索了很多相关问题,也查找了相关的问题,但好像都没有找到。如果我错过了什么,请谅解!

1
有几个原因。首先,应用程序的“路径”不是线性的-不想在各个地方推送和弹出控制器。其次,如果我将一个新的视图控制器推送到堆栈上,堆栈中较低位置的控制器所使用的资源仍然被使用吗?我找不到答案,但不希望发生这种情况。 - GarlicFries
1
此外,我不想使用 UINavigationController。我只是想了解如何在没有它的情况下完成这个任务。 - GarlicFries
控制器名称 == @"book" 的比较是否有效?我很难相信。 - Paul de Lange
@Paul de Lange,这至少是两年前的事了。不确定现在是否仍然适用... - GarlicFries
在最新的Xcode中,这将会有一个“未定义行为”的警告,因为这是错误的。请使用-isEqual:代替。我很确定它从来就不正确。 - Paul de Lange
显示剩余4条评论
2个回答

10

一种很好的方法是使用iOS5+的UIViewController的子视图控制器功能(称为视图控制器容器)来实现。直到我观看了详细解释这一功能的WWDC视频之前,我确实很难理解如何操作。

简而言之,它允许您创建自己的父视图控制器,拥有一系列子视图控制器。这个单一的父视图控制器可以(并且可能应该,除非你正在做一些非常花哨的东西:P)作为您的应用程序窗口的根视图控制器。这种让单个视图控制器作为父级的方法(并促进添加、删除和转换子视图控制器)类似于UINavigationController所做的(这是苹果的意图)。现在,您可以创建自己的类似UINavigationController的父视图控制器,但具有完全不同的过渡动画和用户界面。

例如,在父视图控制器中,我在viewDidLoad中像这样添加第一个子控制器:

self.currentlyDisplayedChildViewController = [[TheFirstViewController alloc] init];
[self addChildViewController:self.currentlyDisplayedChildViewController];
[self.view addSubview:self.currentlyDisplayedChildViewController.view];
[self.currentlyDisplayedChildViewController didMoveToParentViewController:self];

然后我会有一个函数来执行转换到下一个子视图控制器(注意:此函数属于父视图控制器 - 作为您的UINavigationController的视图控制器)

- (void)transitionToViewController:(UIViewController *)nextChildViewController
{
    [self addChildViewController:nextChildViewController];
    __weak TheParentViewController *me = self;
    [self transitionFromViewController:self.currentlyDisplayedChildViewController
                      toViewController:nextChildViewController
                              duration:1.0f
                               options:UIViewAnimationOptionTransitionFlipFromLeft
                            animations:nil
                            completion:^(BOOL finished)
                            {
                                [nextChildViewController didMoveToParentViewController:self];
                                [me.currentlyDisplayedChildViewController willMoveToParentViewController:nil];
                                [me.currentlyDisplayedChildViewController removeFromParentViewController];
                                me.currentlyDisplayedChildViewController = nextChildViewController;
                            }];
}

非常好的一点是,您可以使用所有标准的UIViewAnimationTransition选项(或在动画块中定义自己的自定义动画)。另外,任何方向旋转事件都会自动从父视图控制器转发到子视图控制器。这是在自己进行自定义根视图控制器操作时遇到的最棘手的问题之一。

我建议看一下名为“实现UIViewController容器”的WWDC2011视频。


3

这不是一个坏的解决方案。你可以将一个视图设置为根视图,当你需要另一个UIViewController时就设置另一个。只需小心内存泄漏...

  • 将rootViewController作为类的属性进行保留。
  • 在此之前:

rootViewController = (UIViewController *)[[BookViewController alloc] init];

添加以下内容:

if(rootViewController){
    self.rootViewController=nil;
}

所以您发布先前的版本。

编辑1:有一件事:我的解释是基于您不想使用UINavigationController的事实。


谢谢。不过,有没有更常用或更好的做法呢? - GarlicFries
1
这取决于您的应用程序架构,Brennon。总有更好的解决方案。我们唯一能做的就是在制作应用程序时不断学习,并希望下一次能创建一个更好的应用程序。 - Rui Peres
2
嗯...总觉得接受这样的答案有些奇怪,它基本上是在说:“你已经做得很好了...虽然有更好的解决方案,但我不会告诉你是什么...” - GarlicFries

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接