我们说我有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)
答案 0 :(得分:1)
使用UINavigationViewController然后调用
setViewControllers(_:animated:)
使用此方法更新或替换当前视图控制器堆栈,而无需显式推送或弹出每个控制器。在 此外,此方法允许您在不使用的情况下更新控制器集 动画更改,这可能适用于发布时的时间 您想要将导航控制器返回到先前的状态。
如果启用了动画,则此方法决定使用哪种类型的动画 根据项目中的最后一项进行转换 数组已经在导航堆栈中。如果视图控制器是 目前在堆栈中,但不是最顶层的项目,此方法使用 流行过渡;如果它是最顶级的项目,则没有过渡 执行。如果视图控制器不在堆栈上,则此方法 使用推送过渡。只执行一次转换,但何时执行 转换完成后,堆栈的全部内容都是 替换为新的视图控制器。例如,如果控制器A, B和C在堆栈上,你设置控制器D,A和B,这个 方法使用弹出过渡,结果堆栈包含 控制器D,A和B.
让我知道它是否对你有帮助:)。
答案 1 :(得分:1)
像往常一样推A和B和C,但是使用presentViewController:? animated:NO
和pushViewController:? 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类型:push
,modal
或custom
。
之后,单击Xcode创建的视觉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];
}