显示第n个视图控制器而不显示其根VC

时间:2016-03-10 10:47:30

标签: ios objective-c

我们说我有3个控制器(A,B,C)。 A和C是ViewControllers,B是NavigationController。正常应用流程为A作为根视图,A存在(模态)B,B推C. 我想要的是将C作为顶视图控制器而不通过A-B-C的所有动画,但仍然具有层次结构(意味着C可以返回到A),是否可能?

我们可以将window rooViewController直接设置为C,但它没有层次结构

修改 也许我的问题不够清楚,这里的要点是,当我打开我的应用程序时,我想直接显示C但仍然有A-> B-> C视图层次结构,所以我可以通过普通的pop返回A驳回

EDIT2: 我设法用BC层次结构显示C,所以我可以从C回弹到B.现在我的问题是如何从A(ViewController)呈现 B(NavigationController)所以当我关闭B时它会**解雇*到A

EDIT3: 我看到一些使用NavigationController的答案,它的工作 BUT 不是我想要的,因为通常从A到B我使用模态presentViewController而从B到A我使用dismissViewController

EDIT4: 到目前为止,我得到的是

self.window.rootViewController = vcA;
[self.window makeKeyAndVisible];
[vcA presentViewController:vcB animated:NO completion:nil];
[vcB pushViewController:vcC animated:NO];

这将给出我想要的正确层次结构,但它会给出快速动画(闪烁),显示A和C,并发出警告Unbalanced calls to begin/end appearance transitions for <vcA: 0x7fcfa0cf9c50>.

EDIT5: 我最终无视警告并坚持我的流行答案(但仍然欢迎另一种解决方案)。对于闪烁的问题,我使用下面的解决方法

uiview *overlay = [new uiview]; // using vcA.frame
overlay.backgroundColor = white; // I use dominant color of vcC 
vcA addSubview:overlay;
self.window.rootViewController = vcA;
[self.window makeKeyAndVisible];
[vcA presentViewController:vcB animated:NO completion:^{
    [overlay removeFromSuperview];
}];
[vcB pushViewController:vcC animated:NO];

这会掩盖眨眼的行为,所以没有人会注意到(我希望:-p)

6 个答案:

答案 0 :(得分:1)

使用UINavigationViewController然后调用

setViewControllers(_:animated:)
  
    

使用此方法更新或替换当前视图控制器堆栈,而无需显式推送或弹出每个控制器。在     此外,此方法允许您在不使用的情况下更新控制器集     动画更改,这可能适用于发布时的时间     您想要将导航控制器返回到先前的状态。

  
     

如果启用了动画,则此方法决定使用哪种类型的动画   根据项目中的最后一项进行转换   数组已经在导航堆栈中。如果视图控制器是   目前在堆栈中,但不是最顶层的项目,此方法使用   流行过渡;如果它是最顶级的项目,则没有过渡   执行。如果视图控制器不在堆栈上,则此方法   使用推送过渡。只执行一次转换,但何时执行   转换完成后,堆栈的全部内容都是   替换为新的视图控制器。例如,如果控制器A,   B和C在堆栈上,你设置控制器D,A和B,这个   方法使用弹出过渡,结果堆栈包含   控制器D,A和B.

让我知道它是否对你有帮助:)。

答案 1 :(得分:1)

像往常一样推A和B和C,但是使用presentViewController:? animated:NOpushViewController:? animated:NO来做 - 不是动画就是线索

e.g。 (模拟代码)

applicationDidFinishLaunching {
    id a = [MyA new]; //root, presents b
    id b = [MyA new]; //pushes c you said.. so it is or has a navigationController
    id c = [MyA new];

    [a presentViewController:b animated:NO]; 
    b.navigationController pushViewController:c animated:NO];
}

答案 2 :(得分:0)

为什么不用presentViewController将A放在A之上?

修改

A - &gt; C:

在vcB中,我会添加一个布尔属性,指示我们是否在上述流程中,并以这种方式在vcA中显示vbB:

// We are in vcA where you want to present vcB and vcC
vcB.transient = YES;
[vcA presentViewController:vcB animated:NO completion:^{
    [vcB pushViewController:vcC animated:NO];
}];

C - &gt; A

当您想要返回vcA时,弹出vcC会在vcB中调用viewDidAppear

// We are in vcB
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    if(self.transient == YES) {
        [self dismissViewControllerAnimated:NO completion:nil];
        return;
    }
}

使用此解决方案,当您从vcC返回到vcA时,您将暂时看到vcB,因为我们必须等待viewDidAppear被调用。

编辑2:

或者,如果您不需要直接从vcC返回到vbA,只需使用第一段代码(不需要瞬态属性)。

答案 3 :(得分:0)

将A保留为rootVC(在applicationDidFinishLaunching中)。因此,当您打开应用程序时,它将首先加载A.

加载A后(在viewDidLoad中)调用一个方法来呈现B(在呈现时保持动画= NO)。

加载B时,调用方法推送到C(推动时保持动画= NO)。

希望这有帮助!

答案 4 :(得分:0)

要切换到您想要的任何ViewController:您是否通过按住键盘上的控制键并单击希望segue所在的ViewController,在故事板中绘制了自定义segue?在仍然保持控制的同时,您可以将其拖动到要转移到的视图控制器。之后,只需放手,XCode就可以让您选择所需的segue类型:pushmodalcustom

enter image description here

之后,单击Xco​​de创建的视觉segue引用(看起来像故事板中指向viewcontrolelrs的灰色大箭头),然后单击属性检查器。然后查看identifier所在的位置。从那里你可以命名segue你想要的任何东西,并以编程方式引用它。只需执行以上操作并调用以下消息,您就可以在任何时候访问任何viewcontroller。

[self performSegueWithIdentifier:@"ShowViewControllerA" sender:self];

另外,我同意其他所有人都说将Viewcontroller C设置为故事板中的根ViewController。 PresentViewController也是一个好主意。等

答案 5 :(得分:0)

关注@ Daij-Djan的回答:

applicationDidFinishLaunching {
  id a = [MyA new]; //root, presents b
  id b = [MyA new]; //pushes c you said.. so it is or has a navigationController
  nav d = [[Nav alloc] initWithRoot:b];
  id c = [MyA new];

  [a presentViewController:d animated:NO]; 
  b.navigationController pushViewController:c animated:NO];
}